001: /*
002: * Java program to execute SQL commands using the tinySQL JDBC driver.
003: *
004: * $Author: davis $
005: * $Date: 2004/12/18 21:26:02 $
006: * $Revision: 1.1 $
007: *
008: * This library is free software; you can redistribute it and/or
009: * modify it under the terms of the GNU Lesser General Public
010: * License as published by the Free Software Foundation; either
011: * version 2.1 of the License, or (at your option) any later version.
012: *
013: * This library is distributed in the hope that it will be useful,
014: * but WITHOUT ANY WARRANTY; without even the implied warranty of
015: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
016: * Lesser General Public License for more details.
017: *
018: * You should have received a copy of the GNU Lesser General Public
019: * License along with this library; if not, write to the Free Software
020: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
021: *
022: * Revision History:
023: *
024: * Written by Davis Swan in November, 2003.
025: */
026:
027: package com.sqlmagic.tinysql;
028:
029: import java.io.*;
030: import java.sql.*;
031: import java.net.*;
032: import java.util.*;
033:
034: public class tinySQLCmd {
035: static Vector tableList;
036: static String dbVersion;
037: static FileWriter spoolFileWriter = (FileWriter) null;
038: static String newLine = System.getProperty("line.separator");
039:
040: public static void main(String[] args) throws IOException,
041: SQLException {
042: DatabaseMetaData dbMeta;
043: ResultSetMetaData meta;
044: ResultSet display_rs, typesRS;
045: BufferedReader stdin, loadFileReader;
046: BufferedReader startReader = (BufferedReader) null;
047: String[] fields;
048: Connection con;
049: Statement stmt;
050: FieldTokenizer ft;
051: PreparedStatement pstmt = (PreparedStatement) null;
052: int i, rsColCount, endAt, colWidth, colScale, colPrecision, typeCount, colType, parameterIndex, b1, b2, parameterInt, startAt, columnIndex, valueIndex;
053: String fName, tableName = null, inputString, cmdString, colTypeName, dbType, parameterString, loadString, fieldString, readString;
054: StringBuffer lineOut, prepareBuffer, valuesBuffer, inputBuffer;
055: boolean echo = false;
056: stdin = new BufferedReader(new InputStreamReader(System.in));
057: try {
058: /*
059: * Register the JDBC driver for dBase
060: */
061: Class.forName("com.sqlmagic.tinysql.dbfFileDriver");
062: } catch (ClassNotFoundException e) {
063: System.err
064: .println("JDBC Driver could not be registered!!\n");
065: if (tinySQLGlobals.DEBUG)
066: e.printStackTrace();
067: }
068: fName = ".";
069: if (args.length > 0)
070: fName = args[0];
071: /*
072: * Establish a connection to dBase
073: */
074: con = dbConnect(fName);
075: if (con == (Connection) null) {
076: fName = ".";
077: con = dbConnect(fName);
078: }
079: dbMeta = con.getMetaData();
080: dbType = dbMeta.getDatabaseProductName();
081: dbVersion = dbMeta.getDatabaseProductVersion();
082: System.out
083: .println("===================================================");
084: System.out.println(dbType + " Command line interface version "
085: + dbVersion + " released March 15, 2007");
086: System.out
087: .println("Type HELP to get information on available commands.");
088: cmdString = "NULL";
089: stmt = con.createStatement();
090: inputString = (String) null;
091: if (args.length > 1)
092: inputString = args[1].trim();
093: while (!cmdString.toUpperCase().equals("EXIT")) {
094: try {
095: if (startReader != (BufferedReader) null) {
096: /*
097: * Command START files can contain comments and can have
098: * commands broken over several lines. However, they
099: * cannot have partial commands on a line.
100: */
101: inputBuffer = new StringBuffer();
102: inputString = (String) null;
103: while ((readString = startReader.readLine()) != null) {
104: if (readString.startsWith("--")
105: | readString.startsWith("#"))
106: continue;
107: inputBuffer.append(readString + " ");
108: /*
109: * A field tokenizer must be used to avoid problems with
110: * semi-colons inside quoted strings.
111: */
112: ft = new FieldTokenizer(inputBuffer.toString(),
113: ';', true);
114: if (ft.countFields() > 1) {
115: inputString = inputBuffer.toString();
116: break;
117: }
118: }
119: if (inputString == (String) null) {
120: startReader = (BufferedReader) null;
121: continue;
122: }
123: } else if (args.length == 0) {
124: System.out.print("tinySQL>");
125: inputString = stdin.readLine().trim();
126: }
127: if (inputString == (String) null)
128: break;
129: if (inputString.toUpperCase().startsWith("EXIT")
130: | inputString.toUpperCase().startsWith("QUIT"))
131: break;
132: startAt = 0;
133: while (startAt < inputString.length() - 1) {
134: endAt = inputString.indexOf(";", startAt);
135: if (endAt == -1)
136: endAt = inputString.length();
137: cmdString = inputString.substring(startAt, endAt);
138: if (echo)
139: System.out.println(cmdString);
140: startAt = endAt + 1;
141: if (cmdString.toUpperCase().startsWith("SELECT")) {
142: display_rs = stmt.executeQuery(cmdString);
143: if (display_rs == (ResultSet) null) {
144: System.out
145: .println("Null ResultSet returned from query");
146: continue;
147: }
148: meta = display_rs.getMetaData();
149: /*
150: * The actual number of columns retrieved has to be checked
151: */
152: rsColCount = meta.getColumnCount();
153: lineOut = new StringBuffer(100);
154: int[] columnWidths = new int[rsColCount];
155: int[] columnScales = new int[rsColCount];
156: int[] columnPrecisions = new int[rsColCount];
157: int[] columnTypes = new int[rsColCount];
158: String[] columnNames = new String[rsColCount];
159: for (i = 0; i < rsColCount; i++) {
160: columnNames[i] = meta.getColumnName(i + 1);
161: columnWidths[i] = meta
162: .getColumnDisplaySize(i + 1);
163: columnTypes[i] = meta.getColumnType(i + 1);
164: columnScales[i] = meta.getScale(i + 1);
165: columnPrecisions[i] = meta
166: .getPrecision(i + 1);
167: if (columnNames[i].length() > columnWidths[i])
168: columnWidths[i] = columnNames[i]
169: .length();
170: lineOut.append(padString(columnNames[i],
171: columnWidths[i])
172: + " ");
173: }
174: if (tinySQLGlobals.DEBUG)
175: System.out.println(lineOut.toString());
176: displayResults(display_rs);
177: } else if (cmdString.toUpperCase().startsWith(
178: "CONNECT")) {
179: con = dbConnect(cmdString.substring(8,
180: cmdString.length()));
181: } else if (cmdString.toUpperCase().startsWith(
182: "HELP")) {
183: helpMsg(cmdString);
184: } else if (cmdString.toUpperCase().startsWith(
185: "DESCRIBE")) {
186: dbMeta = con.getMetaData();
187: tableName = cmdString.toUpperCase()
188: .substring(9);
189: display_rs = dbMeta.getColumns(null, null,
190: tableName, null);
191: System.out
192: .println("\nColumns for table "
193: + tableName
194: + "\n"
195: + "Name Type");
196: while (display_rs.next()) {
197: lineOut = new StringBuffer(100);
198: lineOut.append(padString(display_rs
199: .getString(4), 32));
200: colTypeName = display_rs.getString(6);
201: colType = display_rs.getInt(5);
202: colWidth = display_rs.getInt(7);
203: colScale = display_rs.getInt(9);
204: colPrecision = display_rs.getInt(10);
205: if (colTypeName.equals("CHAR")) {
206: colTypeName = colTypeName + "("
207: + Integer.toString(colWidth)
208: + ")";
209: } else if (colTypeName.equals("FLOAT")) {
210: colTypeName += "("
211: + Integer
212: .toString(colPrecision)
213: + ","
214: + Integer.toString(colScale)
215: + ")";
216: }
217: lineOut.append(padString(colTypeName, 20)
218: + padString(colType, 12));
219: System.out.println(lineOut.toString());
220: }
221: } else if (cmdString.toUpperCase().equals(
222: "SHOW TABLES")) {
223: for (i = 0; i < tableList.size(); i++)
224: System.out.println((String) tableList
225: .elementAt(i));
226: } else if (cmdString.toUpperCase().equals(
227: "SHOW TYPES")) {
228: typesRS = dbMeta.getTypeInfo();
229: typeCount = displayResults(typesRS);
230: } else if (cmdString.toUpperCase().startsWith(
231: "SET ")) {
232: /*
233: * Support for SET DEBUG ON/OFF and SET ECHO ON/OFF
234: */
235: ft = new FieldTokenizer(
236: cmdString.toUpperCase(), ' ', false);
237: fields = ft.getFields();
238: if (fields[1].equals("ECHO")) {
239: if (fields[2].equals("ON"))
240: echo = true;
241: else
242: echo = false;
243: } else if (fields[1].equals("DEBUG")) {
244: if (fields[2].equals("ON"))
245: tinySQLGlobals.DEBUG = true;
246: else
247: tinySQLGlobals.DEBUG = false;
248: } else if (fields[1].equals("PARSER_DEBUG")) {
249: if (fields[2].equals("ON"))
250: tinySQLGlobals.PARSER_DEBUG = true;
251: else
252: tinySQLGlobals.PARSER_DEBUG = false;
253: } else if (fields[1].equals("WHERE_DEBUG")) {
254: if (fields[2].equals("ON"))
255: tinySQLGlobals.WHERE_DEBUG = true;
256: else
257: tinySQLGlobals.WHERE_DEBUG = false;
258: } else if (fields[1].equals("EX_DEBUG")) {
259: if (fields[2].equals("ON"))
260: tinySQLGlobals.EX_DEBUG = true;
261: else
262: tinySQLGlobals.EX_DEBUG = false;
263: }
264: } else if (cmdString.toUpperCase().startsWith(
265: "SPOOL ")) {
266: /*
267: * Spool output to a file.
268: */
269: ft = new FieldTokenizer(cmdString, ' ', false);
270: fName = ft.getField(1);
271: if (fName.equals("OFF")) {
272: try {
273: spoolFileWriter.close();
274: } catch (Exception spoolEx) {
275: System.out
276: .println("Unable to close spool file "
277: + spoolEx.getMessage()
278: + newLine);
279: }
280: } else {
281: try {
282: spoolFileWriter = new FileWriter(fName);
283: if (spoolFileWriter != (FileWriter) null)
284: System.out
285: .println("Output spooled to "
286: + fName);
287: } catch (Exception spoolEx) {
288: System.out
289: .println("Unable to spool to file "
290: + spoolEx.getMessage()
291: + newLine);
292: }
293: }
294: } else if (cmdString.toUpperCase().startsWith(
295: "START ")) {
296: ft = new FieldTokenizer(cmdString, ' ', false);
297: fName = ft.getField(1);
298: if (!fName.toUpperCase().endsWith(".SQL"))
299: fName += ".SQL";
300: try {
301: startReader = new BufferedReader(
302: new FileReader(fName));
303: } catch (Exception ex) {
304: startReader = (BufferedReader) null;
305: throw new tinySQLException("No such file: "
306: + fName);
307: }
308: } else if (cmdString.toUpperCase().startsWith(
309: "LOAD")) {
310: ft = new FieldTokenizer(cmdString, ' ', false);
311: fName = ft.getField(1);
312: tableName = ft.getField(3);
313: display_rs = stmt.executeQuery("SELECT * FROM "
314: + tableName);
315: meta = display_rs.getMetaData();
316: rsColCount = meta.getColumnCount();
317: /*
318: * Set up the PreparedStatement for the inserts
319: */
320: prepareBuffer = new StringBuffer("INSERT INTO "
321: + tableName);
322: valuesBuffer = new StringBuffer(" VALUES");
323: for (i = 0; i < rsColCount; i++) {
324: if (i == 0) {
325: prepareBuffer.append(" (");
326: valuesBuffer.append(" (");
327: } else {
328: prepareBuffer.append(",");
329: valuesBuffer.append(",");
330: }
331: prepareBuffer.append(meta
332: .getColumnName(i + 1));
333: valuesBuffer.append("?");
334: }
335: prepareBuffer.append(")"
336: + valuesBuffer.toString() + ")");
337: try {
338: pstmt = con.prepareStatement(prepareBuffer
339: .toString());
340: loadFileReader = new BufferedReader(
341: new FileReader(fName));
342: while ((loadString = loadFileReader
343: .readLine()) != null) {
344: if (loadString.toUpperCase().equals(
345: "ENDOFDATA"))
346: break;
347: columnIndex = 0;
348: valueIndex = 0;
349: ft = new FieldTokenizer(loadString,
350: '|', true);
351: while (ft.hasMoreFields()) {
352: fieldString = ft.nextField();
353: if (fieldString.equals("|")) {
354: columnIndex++;
355: if (columnIndex > valueIndex) {
356: pstmt.setString(
357: valueIndex + 1,
358: (String) null);
359: valueIndex++;
360: }
361: } else if (columnIndex < rsColCount) {
362: pstmt.setString(valueIndex + 1,
363: fieldString);
364: valueIndex++;
365: }
366: }
367: pstmt.executeUpdate();
368: }
369: pstmt.close();
370: } catch (Exception loadEx) {
371: System.out.println(loadEx.getMessage());
372: }
373: } else if (cmdString.toUpperCase().startsWith(
374: "SETSTRING")
375: | cmdString.toUpperCase().startsWith(
376: "SETINT")) {
377: b1 = cmdString.indexOf(" ");
378: b2 = cmdString.lastIndexOf(" ");
379: if (b2 > b1 & b1 > 0) {
380: parameterIndex = Integer.parseInt(cmdString
381: .substring(b1 + 1, b2));
382: parameterString = cmdString
383: .substring(b2 + 1);
384: if (tinySQLGlobals.DEBUG)
385: System.out.println("Set parameter["
386: + parameterIndex + "]="
387: + parameterString);
388: if (cmdString.toUpperCase().startsWith(
389: "SETINT")) {
390: parameterInt = Integer
391: .parseInt(parameterString);
392: pstmt.setInt(parameterIndex,
393: parameterInt);
394: } else {
395: pstmt.setString(parameterIndex,
396: parameterString);
397: }
398: if (parameterIndex == 2)
399: pstmt.executeUpdate();
400: }
401: } else {
402: if (cmdString.indexOf("?") > -1) {
403: pstmt = con.prepareStatement(cmdString);
404: } else {
405: try {
406: stmt.executeUpdate(cmdString);
407: System.out.println("DONE\n");
408: } catch (Exception upex) {
409: System.out.println(upex.getMessage());
410: if (tinySQLGlobals.DEBUG)
411: upex.printStackTrace();
412: }
413: }
414: }
415: }
416: if (args.length > 1)
417: cmdString = "EXIT";
418: } catch (SQLException te) {
419: System.out.println(te.getMessage());
420: if (tinySQLGlobals.DEBUG)
421: te.printStackTrace(System.out);
422: inputString = (String) null;
423: } catch (Exception e) {
424: System.out.println(e.getMessage());
425: cmdString = "EXIT";
426: break;
427: }
428: }
429: try {
430: if (spoolFileWriter != (FileWriter) null)
431: spoolFileWriter.close();
432: } catch (Exception spoolEx) {
433: System.out.println("Unable to close spool file "
434: + spoolEx.getMessage() + newLine);
435: }
436: }
437:
438: private static void helpMsg(String inputCmd) {
439: String upperCmd;
440: upperCmd = inputCmd.toUpperCase().trim();
441: if (upperCmd.equals("HELP")) {
442: System.out
443: .println("The following help topics are available:\n"
444: + "=============================================================\n"
445: + "HELP NEW - list of new features in tinySQL "
446: + dbVersion
447: + "\n"
448: + "HELP COMMANDS - help for the non-SQL commands\n"
449: + "HELP LIMITATIONS - limitations of tinySQL "
450: + dbVersion
451: + "\n"
452: + "HELP ABOUT - short description of tinySQL.\n");
453: } else if (upperCmd.equals("HELP COMMANDS")) {
454: System.out
455: .println("The following non-SQL commands are supported:\n"
456: + "=============================================================\n"
457: + "SHOW TABLES - lists the tinySQL tables (DBF files) in the current "
458: + "directory\n"
459: + "SHOW TYPES - lists column types supported by tinySQL.\n"
460: + "DESCRIBE table_name - describes the columns in table table_name.\n"
461: + "CONNECT directory - connects to a different directory;\n"
462: + " Examples: CONNECT C:\\TEMP in Windows\n"
463: + " CONNECT /home/mydir/temp in Linux/Unix\n"
464: + "SET DEBUG ON/OFF - turns general debugging on or off\n"
465: + "SET PARSER_DEBUG ON/OFF - turns parser debugging on or off\n"
466: + "SET WHERE_DEBUG ON/OFF - turns where clause debugging on or off\n"
467: + "SET EX_DEBUG ON/OFF - turns exception stack printing on or off\n"
468: + "SET ECHO ON/OFF - will echo input commands\n"
469: + "START <filename> - executes commands in the text file\n"
470: + "SPOOL <filename> - spools output of commands to the file\n"
471: + "EXIT - leave the tinySQL command line interface.\n");
472: } else if (upperCmd.equals("HELP LIMITATIONS")) {
473: System.out
474: .println("tinySQL "
475: + dbVersion
476: + " does NOT support the following:\n"
477: + "=============================================================\n"
478: + "Subqueries: eg SELECT COL1 from TABLE1 where COL2 in (SELECT ...\n"
479: + "IN specification within a WHERE clause.\n"
480: + "GROUP BY clause in SELECT statments.\n"
481: + "AS in CREATE statements; eg CREATE TABLE TAB2 AS SELECT ...\n"
482: + "UPDATE statements including JOINS.\n\n"
483: + "If you run into others let us know by visiting\n"
484: + "http://sourceforge.net/projects/tinysql\n");
485: } else if (upperCmd.equals("HELP NEW")) {
486: System.out
487: .println("New features in tinySQL releases.\n"
488: + "=============================================================\n"
489: + "Version 2.26h released March 15, 2007\n"
490: + "Corrected problems with date comparisions, added support for \n"
491: + "the TO_DATE function, corrected problems with DELETE.\n"
492: + "Added support for IS NULL and IS NOT NULL, added ability\n"
493: + "to spool output to a file.\n"
494: + "---------------------------------------------------------------\n"
495: + "Version 2.10 released October 22, 2006\n"
496: + "Added support for long column names and fixed bugs in \n"
497: + "ALTER TABLE commands.\n"
498: + "---------------------------------------------------------------\n"
499: + "Version 2.02 released July 20, 2005\n"
500: + "Fixed more bugs with the COUNT(*) and the like comparison.\n"
501: + "---------------------------------------------------------------\n"
502: + "Version 2.01 released April 20, 2005\n"
503: + "Fixed several bugs with the COUNT(*) and other summary functions\n"
504: + "Fixed ORDER BY using columns that were not SELECTed.\n"
505: + "Added support for DISTINCT keyword and TRIM function.\n"
506: + "Added default sorting by selected column.\n"
507: + "Significant reorganization of code to allow the use of functions\n"
508: + "in WHERE clauses (now stores tsColumn objects in tinySQLWhere).\n"
509: + "---------------------------------------------------------------\n"
510: + "Version 2.0 released Dec. 20, 2004\n"
511: + "The package name was changed to com.sqlmagic.tinysql.\n"
512: + "Support for table aliases in JOINS: see example below\n"
513: + " SELECT A.COL1,B.COL2 FROM TABLE1 A,TABLE2 B WHERE A.COL3=B.COL3\n"
514: + "COUNT,MAX,MIN,SUM aggregate functions.\n"
515: + "CONCAT,UPPER,SUBSTR in-line functions for strings.\n"
516: + "SYSDATE - current date.\n"
517: + "START script_file.sql - executes SQL commands in file.\n"
518: + "Support for selection of constants: see example below:\n"
519: + " SELECT 'Full Name: ',first_name,last_name from person\n"
520: + "All comparisions work properly: < > = != LIKE \n");
521: } else if (upperCmd.equals("HELP ABOUT")) {
522: System.out
523: .println("=============================================================\n"
524: + "tinySQL was originally written by Brian Jepson\n"
525: + "as part of the research he did while writing the book \n"
526: + "Java Database Programming (John Wiley, 1996). The database was\n"
527: + "enhanced by Andreas Kraft, Thomas Morgner, Edson Alves Pereira,\n"
528: + "and Marcel Ruff between 1997 and 2002.\n"
529: + "The current version "
530: + dbVersion
531: + " was developed by Davis Swan starting in 2004.\n\n"
532: + "tinySQL is free software; you can redistribute it and/or\n"
533: + "modify it under the terms of the GNU Lesser General Public\n"
534: + "License as published by the Free Software Foundation; either\n"
535: + "version 2.1 of the License, or (at your option) any later version.\n"
536: + "This library is distributed in the hope that it will be useful,\n"
537: + "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
538: + "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n"
539: + "Lesser General Public License for more details at\n"
540: + "http://www.gnu.org/licenses/lgpl.html");
541: } else {
542: System.out.println("Unknown help command.\n");
543: }
544: }
545:
546: private static String padString(int inputint, int padLength) {
547: return padString(Integer.toString(inputint), padLength);
548: }
549:
550: private static String padString(String inputString, int padLength) {
551: StringBuffer outputBuffer;
552: String blanks = " ";
553: if (inputString != (String) null)
554: outputBuffer = new StringBuffer(inputString);
555: else
556: outputBuffer = new StringBuffer(blanks);
557: while (outputBuffer.length() < padLength)
558: outputBuffer.append(blanks);
559: return outputBuffer.toString().substring(0, padLength);
560: }
561:
562: private static Connection dbConnect(String tinySQLDir)
563: throws SQLException {
564: Connection con = null;
565: DatabaseMetaData dbMeta;
566: File conPath;
567: File[] fileList;
568: String tableName;
569: ResultSet tables_rs;
570: conPath = new File(tinySQLDir);
571: fileList = conPath.listFiles();
572: if (fileList == null) {
573: System.out.println(tinySQLDir
574: + " is not a valid directory.");
575: return (Connection) null;
576: } else {
577: System.out.println("Connecting to "
578: + conPath.getAbsolutePath());
579: con = DriverManager.getConnection(
580: "jdbc:dbfFile:" + conPath, "", "");
581: }
582: dbMeta = con.getMetaData();
583: tables_rs = dbMeta.getTables(null, null, null, null);
584: tableList = new Vector();
585: while (tables_rs.next()) {
586: tableName = tables_rs.getString("TABLE_NAME");
587: tableList.addElement(tableName);
588: }
589: if (tableList.size() == 0)
590: System.out
591: .println("There are no tinySQL tables in this directory.");
592: else
593: System.out.println("There are " + tableList.size()
594: + " tinySQL tables" + " in this directory.");
595: return con;
596: }
597:
598: /**
599: Formatted output to stdout
600: @return number of tuples
601: */
602: static int displayResults(ResultSet rs)
603: throws java.sql.SQLException {
604: if (rs == null) {
605: System.err
606: .println("ERROR in displayResult(): No data in ResultSet");
607: return 0;
608: }
609: java.sql.Date testDate;
610: int numCols = 0, nameLength;
611: ResultSetMetaData meta = rs.getMetaData();
612: int cols = meta.getColumnCount();
613: int[] width = new int[cols];
614: String dashes = "=============================================";
615: /*
616: * Display column headers
617: */
618: boolean first = true;
619: StringBuffer head = new StringBuffer();
620: StringBuffer line = new StringBuffer();
621: /*
622: * Fetch each row
623: */
624: while (rs.next()) {
625: /*
626: * Get the column, and see if it matches our expectations
627: */
628: String text = new String();
629: for (int ii = 0; ii < cols; ii++) {
630: String value = rs.getString(ii + 1);
631: if (first) {
632: width[ii] = meta.getColumnDisplaySize(ii + 1);
633: if (tinySQLGlobals.DEBUG
634: & meta.getColumnType(ii + 1) == Types.DATE) {
635: testDate = rs.getDate(ii + 1);
636: System.out.println("Value " + value + ", Date "
637: + testDate.toString());
638: }
639: nameLength = meta.getColumnName(ii + 1).length();
640: if (nameLength > width[ii])
641: width[ii] = nameLength;
642: head.append(padString(meta.getColumnName(ii + 1),
643: width[ii]));
644: head.append(" ");
645: line.append(padString(dashes + dashes, width[ii]));
646: line.append(" ");
647: }
648: text += padString(value, width[ii]);
649: text += " "; // the gap between the columns
650: }
651: try {
652: if (first) {
653: if (spoolFileWriter != (FileWriter) null) {
654: spoolFileWriter
655: .write(head.toString() + newLine);
656: spoolFileWriter
657: .write(head.toString() + newLine);
658: } else {
659: System.out.println(head.toString());
660: System.out.println(line.toString());
661: }
662: first = false;
663: }
664: if (spoolFileWriter != (FileWriter) null)
665: spoolFileWriter.write(text + newLine);
666: else
667: System.out.println(text);
668: numCols++;
669: } catch (Exception writeEx) {
670: System.out.println("Exception writing to spool file "
671: + writeEx.getMessage());
672: }
673: }
674: return numCols;
675: }
676: }
|