KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > Ostermiller > util > ExcelCSVPrinter


1 /*
2  * Write files in Excel comma separated value format.
3  * Copyright (C) 2001-2004 Stephen Ostermiller
4  * http://ostermiller.org/contact.pl?regarding=Java+Utilities
5  * Copyright (C) 2003 Pierre Dittgen <pierre dot dittgen at pass-tech dot fr>
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * See COPYING.TXT for details.
18  */

19
20 package com.Ostermiller.util;
21 import java.io.*;
22
23 /**
24  * Print values as a comma separated list that can be read by the
25  * Excel spreadsheet.
26  * More information about this class is available from <a target="_top" HREF=
27  * "http://ostermiller.org/utils/ExcelCSV.html">ostermiller.org</a>.
28  *
29  * @author Stephen Ostermiller http://ostermiller.org/contact.pl?regarding=Java+Utilities
30  * @author Pierre Dittgen <pierre dot dittgen at pass-tech dot fr>
31  * @since ostermillerutils 1.00.00
32  */

33 public class ExcelCSVPrinter implements CSVPrint {
34
35     /**
36      * If auto flushing is enabled.
37      *
38      * @since ostermillerutils 1.02.26
39      */

40     protected boolean autoFlush = true;
41
42     /**
43      * If auto flushing is enabled.
44      *
45      * @since ostermillerutils 1.02.26
46      */

47     protected boolean alwaysQuote = false;
48
49     /**
50      * true iff an error has occurred.
51      *
52      * @since ostermillerutils 1.02.26
53      */

54     protected boolean error = false;
55
56     /**
57      * Delimiter character written.
58      *
59      * @since ostermillerutils 1.02.18
60      */

61     protected char delimiterChar = ',';
62
63     /**
64      * Quoting character written.
65      *
66      * @since ostermillerutils 1.02.18
67      */

68     protected char quoteChar = '"';
69
70     /**
71      * The place that the values get written.
72      *
73      * @since ostermillerutils 1.00.00
74      */

75     protected Writer out;
76
77     /**
78      * True iff we just began a new line.
79      *
80      * @since ostermillerutils 1.00.00
81      */

82     protected boolean newLine = true;
83
84     /**
85      * Create a printer that will print values to the given
86      * stream. Character to byte conversion is done using
87      * the default character encoding. The delimiter will
88      * be the comma, the quote character will be double quotes,
89      * quotes will be used when needed, and auto flushing
90      * will be enabled.
91      *
92      * @param out stream to which to print.
93      *
94      * @since ostermillerutils 1.00.00
95      */

96     public ExcelCSVPrinter(OutputStream out){
97         this.out = new OutputStreamWriter(out);
98     }
99
100     /**
101      * Create a printer that will print values to the given
102      * stream. The delimiter will
103      * be the comma, the quote character will be double quotes,
104      * quotes will be used when needed, and auto flushing
105      * will be enabled.
106      *
107      * @param out stream to which to print.
108      *
109      * @since ostermillerutils 1.00.00
110      */

111     public ExcelCSVPrinter(Writer out){
112         this.out = out;
113     }
114
115     /**
116      * Create a printer that will print values to the given
117      * stream. The delimiter will
118      * be the comma, and the quote character will be double quotes.
119      *
120      * @param out stream to which to print.
121      * @param alwaysQuote true if quotes should be used even when not strictly needed.
122      * @param autoFlush should auto flushing be enabled.
123      *
124      * @since ostermillerutils 1.02.26
125      */

126     public ExcelCSVPrinter(Writer out, boolean alwaysQuote, boolean autoFlush){
127         this.out = out;
128         setAlwaysQuote(alwaysQuote);
129         setAutoFlush(autoFlush);
130     }
131
132     /**
133      * Create a printer that will print values to the given
134      * stream. Quotes will be used when needed, and auto flushing
135      * will be enabled.
136      *
137      * @param out stream to which to print.
138      * @param delimiter The new delimiter character to use.
139      * @param quote The new character to use for quoting.
140      * @throws BadQuoteException if the character cannot be used as a quote.
141      * @throws BadDelimiterException if the character cannot be used as a delimiter.
142      *
143      * @since ostermillerutils 1.02.26
144      */

145     public ExcelCSVPrinter(Writer out, char quote, char delimiter) throws BadDelimiterException, BadQuoteException {
146         this.out = out;
147         changeQuote(quote);
148         changeDelimiter(delimiter);
149     }
150
151     /**
152      * Create a printer that will print values to the given
153      * stream.
154      *
155      * @param out stream to which to print.
156      * @param delimiter The new delimiter character to use.
157      * @param quote The new character to use for quoting.
158      * @param alwaysQuote true if quotes should be used even when not strictly needed.
159      * @param autoFlush should auto flushing be enabled.
160      * @throws BadQuoteException if the character cannot be used as a quote.
161      * @throws BadDelimiterException if the character cannot be used as a delimiter.
162      *
163      * @since ostermillerutils 1.02.26
164      */

165     public ExcelCSVPrinter(Writer out, char quote, char delimiter, boolean alwaysQuote, boolean autoFlush) throws BadDelimiterException, BadQuoteException {
166         this.out = out;
167         changeQuote(quote);
168         changeDelimiter(delimiter);
169         setAlwaysQuote(alwaysQuote);
170         setAutoFlush(autoFlush);
171     }
172
173     /**
174      * Change this printer so that it uses a new delimiter.
175      *
176      * @param newDelimiter The new delimiter character to use.
177      * @throws BadDelimiterException if the character cannot be used as a delimiter.
178      *
179      * @author Pierre Dittgen <pierre dot dittgen at pass-tech dot fr>
180      * @since ostermillerutils 1.02.18
181      */

182     public void changeDelimiter(char newDelimiter) throws BadDelimiterException {
183         if (delimiterChar == newDelimiter) return; // no need to do anything.
184
if (newDelimiter == '\n' || newDelimiter == '\r' ||
185                 newDelimiter == delimiterChar || newDelimiter == quoteChar){
186             throw new BadDelimiterException();
187         }
188         delimiterChar = newDelimiter;
189     }
190
191     /**
192      * Change this printer so that it uses a new character for quoting.
193      *
194      * @param newQuote The new character to use for quoting.
195      * @throws BadQuoteException if the character cannot be used as a quote.
196      *
197      * @author Pierre Dittgen <pierre dot dittgen at pass-tech dot fr>
198      * @since ostermillerutils 1.02.18
199      */

200     public void changeQuote(char newQuote) throws BadQuoteException {
201         if (quoteChar == newQuote) return; // no need to do anything.
202
if (newQuote == '\n' || newQuote == '\r' ||
203                 newQuote == delimiterChar || newQuote == quoteChar){
204             throw new BadQuoteException();
205         }
206         quoteChar = newQuote;
207     }
208
209     /**
210      * Print the string as the last value on the line. The value
211      * will be quoted if needed.
212      * <p>
213      * This method never throws an I/O exception. The client may inquire as to whether
214      * any errors have occurred by invoking checkError(). If an I/O Exception is
215      * desired, the client should use the corresponding writeln method.
216      *
217      * @param value value to be outputted.
218      *
219      * @since ostermillerutils 1.00.00
220      */

221     public void println(String JavaDoc value){
222         try {
223             writeln(value);
224         } catch (IOException iox){
225             error = true;
226         }
227     }
228
229     /**
230      * Print the string as the last value on the line. The value
231      * will be quoted if needed.
232      *
233      * @param value value to be outputted.
234      * @throws IOException if an error occurs while writing.
235      *
236      * @since ostermillerutils 1.02.26
237      */

238     public void writeln(String JavaDoc value) throws IOException {
239         try {
240             write(value);
241             writeln();
242         } catch (IOException iox){
243             error = true;
244             throw iox;
245         }
246     }
247
248     /**
249      * Output a blank line.
250      * <p>
251      * This method never throws an I/O exception. The client may inquire as to whether
252      * any errors have occurred by invoking checkError(). If an I/O Exception is
253      * desired, the client should use the corresponding writeln method.
254      *
255      * @since ostermillerutils 1.00.00
256      */

257     public void println(){
258         try {
259             writeln();
260         } catch (IOException iox){
261             error = true;
262         }
263     }
264
265     /**
266      * Output a blank line.
267      *
268      * @throws IOException if an error occurs while writing.
269      *
270      * @since ostermillerutils 1.02.26
271      */

272     public void writeln() throws IOException {
273         try {
274             out.write("\n");
275             if (autoFlush) flush();
276             newLine = true;
277         } catch (IOException iox){
278             error = true;
279             throw iox;
280         }
281     }
282
283     /**
284      * Print a single line of comma separated values.
285      * The values will be quoted if needed. Quotes and
286      * and other characters that need it will be escaped.
287      * <p>
288      * This method never throws an I/O exception. The client may inquire as to whether
289      * any errors have occurred by invoking checkError(). If an I/O Exception is
290      * desired, the client should use the corresponding writeln method.
291      *
292      * @param values values to be outputted.
293      *
294      * @since ostermillerutils 1.00.00
295      */

296     public void println(String JavaDoc[] values){
297         try {
298             writeln(values);
299         } catch (IOException iox){
300             error = true;
301         }
302     }
303
304     /**
305      * Print a single line of comma separated values.
306      * The values will be quoted if needed. Quotes and
307      * and other characters that need it will be escaped.
308      *
309      * @param values values to be outputted.
310      * @throws IOException if an error occurs while writing.
311      *
312      * @since ostermillerutils 1.02.26
313      */

314     public void writeln(String JavaDoc[] values) throws IOException {
315         try {
316             print(values);
317             writeln();
318         } catch (IOException iox){
319             error = true;
320             throw iox;
321         }
322     }
323
324     /**
325      * Print a single line of comma separated values.
326      * The values will be quoted if needed. Quotes and
327      * and other characters that need it will be escaped.
328      * <p>
329      * This method never throws an I/O exception. The client may inquire as to whether
330      * any errors have occurred by invoking checkError(). If an I/O Exception is
331      * desired, the client should use the corresponding writeln method.
332      *
333      * @param values values to be outputted.
334      *
335      * @since ostermillerutils 1.00.00
336      */

337     public void print(String JavaDoc[] values){
338         try {
339             write(values);
340         } catch (IOException iox){
341             error = true;
342         }
343     }
344
345     /**
346      * Print a single line of comma separated values.
347      * The values will be quoted if needed. Quotes and
348      * and other characters that need it will be escaped.
349      *
350      * @param values values to be outputted.
351      * @throws IOException if an error occurs while writing.
352      *
353      * @since ostermillerutils 1.02.26
354      */

355     public void write(String JavaDoc[] values) throws IOException {
356         try {
357             for (int i=0; i<values.length; i++){
358                 write(values[i]);
359             }
360         } catch (IOException iox){
361             error = true;
362             throw iox;
363         }
364     }
365
366     /**
367      * Print several lines of comma separated values.
368      * The values will be quoted if needed. Quotes and
369      * newLine characters will be escaped.
370      * <p>
371      * This method never throws an I/O exception. The client may inquire as to whether
372      * any errors have occurred by invoking checkError(). If an I/O Exception is
373      * desired, the client should use the corresponding writeln method.
374      *
375      * @param values values to be outputted.
376      *
377      * @since ostermillerutils 1.00.00
378      */

379     public void println(String JavaDoc[][] values){
380         try {
381             writeln(values);
382         } catch (IOException iox){
383             error = true;
384         }
385     }
386
387     /**
388      * Print several lines of comma separated values.
389      * The values will be quoted if needed. Quotes and
390      * newLine characters will be escaped.
391      *
392      * @param values values to be outputted.
393      * @throws IOException if an error occurs while writing.
394      *
395      * @since ostermillerutils 1.02.26
396      */

397     public void writeln(String JavaDoc[][] values) throws IOException {
398         try {
399             for (int i=0; i<values.length; i++){
400                 writeln(values[i]);
401             }
402             if (values.length == 0){
403                 writeln();
404             }
405         } catch (IOException iox){
406             error = true;
407             throw iox;
408         }
409     }
410
411     /**
412      * Since ExcelCSV format does not support comments,
413      * this method will ignore the comment and start
414      * a new row.
415      * <p>
416      * This method never throws an I/O exception. The client may inquire as to whether
417      * any errors have occurred by invoking checkError(). If an I/O Exception is
418      * desired, the client should use the corresponding writelnComment method.
419      *
420      * @param comment the comment to output (ignored).
421      *
422      * @since ostermillerutils 1.00.00
423      */

424     public void printlnComment(String JavaDoc comment){
425         println();
426     }
427
428     /**
429      * Since ExcelCSV format does not support comments,
430      * this method will ignore the comment and start
431      * a new row.
432      *
433      * @param comment the comment to output (ignored).
434      * @throws IOException if an error occurs while writing.
435      *
436      * @since ostermillerutils 1.02.26
437      */

438     public void writelnComment(String JavaDoc comment) throws IOException {
439         writeln();
440     }
441
442     /**
443      * Print the string as the next value on the line. The value
444      * will be quoted if needed. If value is null, an empty value is printed.
445      * <p>
446      * This method never throws an I/O exception. The client may inquire as to whether
447      * any errors have occurred by invoking checkError(). If an I/O Exception is
448      * desired, the client should use the corresponding println method.
449      *
450      * @param value value to be outputted.
451      *
452      * @since ostermillerutils 1.00.00
453      */

454     public void print(String JavaDoc value){
455         try {
456             write(value);
457         } catch (IOException iox){
458             error = true;
459         }
460     }
461
462     /**
463      * Print the string as the next value on the line. The value
464      * will be quoted if needed. If value is null, an empty value is printed.
465      *
466      * @param value value to be outputted.
467      * @throws IOException if an error occurs while writing.
468      *
469      * @since ostermillerutils 1.02.26
470      */

471     public void write(String JavaDoc value) throws IOException {
472         try {
473             if (value == null) value = "";
474             boolean quote = false;
475             if (alwaysQuote){
476                 quote = true;
477             } else if (value.length() > 0){
478                 for (int i=0; i<value.length(); i++){
479                     char c = value.charAt(i);
480                     if (c==quoteChar || c==delimiterChar || c=='\n' || c=='\r'){
481                         quote = true;
482                     }
483                 }
484             } else if (newLine) {
485                 // always quote an empty token that is the firs
486
// on the line, as it may be the only thing on the
487
// line. If it were not quoted in that case,
488
// an empty line has no tokens.
489
quote = true;
490             }
491             if (newLine){
492                 newLine = false;
493             } else {
494                 out.write(delimiterChar);
495             }
496             if (quote){
497                 out.write(escapeAndQuote(value));
498             } else {
499                 out.write(value);
500             }
501             if (autoFlush) flush();
502         } catch (IOException iox){
503             error = true;
504             throw iox;
505         }
506     }
507
508     /**
509      * Enclose the value in quotes and escape the quote
510      * and comma characters that are inside.
511      *
512      * @param value needs to be escaped and quoted.
513      *
514      * @return the value, escaped and quoted.
515      * @since ostermillerutils 1.00.00
516      */

517     private String JavaDoc escapeAndQuote(String JavaDoc value){
518         String JavaDoc s = StringHelper.replace(value, String.valueOf(quoteChar), String.valueOf(quoteChar) + String.valueOf(quoteChar));
519         return (new StringBuffer JavaDoc(2 + s.length())).append(quoteChar).append(s).append(quoteChar).toString();
520     }
521
522     /**
523      * Flush any data written out to underlying streams.
524      *
525      * @since ostermillerutils 1.02.26
526      */

527     public void flush() throws IOException {
528         out.flush();
529     }
530
531     /**
532      * Close any underlying streams.
533      *
534      * @since ostermillerutils 1.02.26
535      */

536     public void close() throws IOException {
537         out.close();
538     }
539
540     /**
541      * Flush the stream if it's not closed and check its error state.
542      * Errors are cumulative; once the stream encounters an error,
543      * this routine will return true on all successive calls.
544      *
545      * @return True if the print stream has encountered an error,
546      * either on the underlying output stream or during a format conversion.
547      *
548      * @since ostermillerutils 1.02.26
549      */

550     public boolean checkError(){
551         try {
552             if (error) return true;
553             flush();
554             if (error) return true;
555             if (out instanceof PrintWriter){
556                 error = ((PrintWriter)out).checkError();
557             }
558         } catch (IOException iox){
559             error = true;
560         }
561         return error;
562     }
563
564     /**
565      * Set whether values printers should always be quoted, or
566      * whether the printer may, at its discretion, omit quotes
567      * around the value.
568      *
569      * @param alwaysQuote true if quotes should be used even when not strictly needed.
570      *
571      * @since ostermillerutils 1.02.26
572      */

573     public void setAlwaysQuote(boolean alwaysQuote){
574         this.alwaysQuote = alwaysQuote;
575     }
576
577     /**
578      * Set flushing behavior. Iff set, a flush command
579      * will be issued to any underlying stream after each
580      * print or write command.
581      *
582      * @param autoFlush should auto flushing be enabled.
583      *
584      * @since ostermillerutils 1.02.26
585      */

586     public void setAutoFlush(boolean autoFlush){
587         this.autoFlush = autoFlush;
588     }
589
590     /**
591      * Write some test data to the given file.
592      *
593      * @param args First argument is the file name. System.out used if no filename given.
594      *
595      * @since ostermillerutils 1.00.00
596      */

597     private static void main(String JavaDoc[] args) {
598         OutputStream out;
599         try {
600             if (args.length > 0){
601                 File f = new File(args[0]);
602                 if (!f.exists()){
603                     f.createNewFile();
604                     if (f.canWrite()){
605                         out = new FileOutputStream(f);
606                     } else {
607                         throw new IOException("Could not open " + args[0]);
608                     }
609                 } else {
610                     throw new IOException("File already exists: " + args[0]);
611                 }
612             } else {
613                 out = System.out;
614             }
615             ExcelCSVPrinter p = new ExcelCSVPrinter(out);
616             p.print("unquoted");
617             p.print("escaped\"quote");
618             p.println("comma,comma");
619             p.print("!quoted");
620             p.print("!unquoted");
621             p.print(" quoted");
622             p.println("quoted ");
623             p.print("one");
624             p.print("");
625             p.print("");
626             p.print("");
627             p.println("");
628             p.println("two");
629             p.print("\nthree\nline\n");
630             p.println("\ttab");
631         } catch (IOException e){
632             System.out.println(e.getMessage());
633         }
634     }
635 }
636
Popular Tags