]> git.argeo.org Git - lgpl/argeo-commons.git/blob - CsvWriter.java
85356e4fed07c4f24e9f980698a983c85d1a17d9
[lgpl/argeo-commons.git] / CsvWriter.java
1 package org.argeo.util;
2
3 import java.io.IOException;
4 import java.io.OutputStream;
5 import java.io.PrintWriter;
6 import java.util.Iterator;
7 import java.util.List;
8
9 import org.argeo.ArgeoException;
10
11 /** Write in CSV format. */
12 public class CsvWriter {
13 private final PrintWriter out;
14
15 private char separator = ',';
16 private char quote = '\"';
17
18 /**
19 * Creates a CSV writer. The header will be written immediately to the
20 * stream.
21 *
22 * @param out
23 * the stream to write to. Caller is responsible for closing it.
24 */
25 public CsvWriter(OutputStream out) {
26 super();
27 this.out = new PrintWriter(out);
28 }
29
30 /**
31 * Write a CSV line. Also used to write a header if needed (this is
32 * transparent for the CSV writer): simply call it first, before writing the
33 * lines.
34 */
35 public void writeLine(List<?> tokens) {
36 try {
37 Iterator<?> it = tokens.iterator();
38 while (it.hasNext()) {
39 writeToken(it.next().toString());
40 if (it.hasNext())
41 out.print(separator);
42 }
43 out.print('\n');
44 out.flush();
45 } catch (IOException e) {
46 throw new ArgeoException("Could not write " + tokens, e);
47 }
48 }
49
50 /**
51 * Write a CSV line. Also used to write a header if needed (this is
52 * transparent for the CSV writer): simply call it first, before writing the
53 * lines.
54 */
55 public void writeLine(Object[] tokens) {
56 try {
57 for (int i = 0; i < tokens.length; i++) {
58 writeToken(tokens[i].toString());
59 if (i != (tokens.length - 1))
60 out.print(separator);
61 }
62 out.print('\n');
63 out.flush();
64 } catch (IOException e) {
65 throw new ArgeoException("Could not write " + tokens, e);
66 }
67 }
68
69 protected void writeToken(String token) throws IOException {
70 // +2 for possible quotes, another +2 assuming there would be an already
71 // quoted string where quotes needs to be duplicated
72 // another +2 for safety
73 StringBuffer buf = new StringBuffer(token.length() + 6);
74 char[] arr = token.toCharArray();
75 boolean shouldQuote = false;
76 for (char c : arr) {
77 if (!shouldQuote) {
78 if (c == separator)
79 shouldQuote = true;
80 if (c == '\n')
81 shouldQuote = true;
82 }
83
84 if (c == quote) {
85 shouldQuote = true;
86 // duplicate quote
87 buf.append(quote);
88 }
89
90 // generic case
91 buf.append(c);
92 }
93
94 if (shouldQuote == true)
95 out.print(quote);
96 out.print(buf.toString());
97 if (shouldQuote == true)
98 out.print(quote);
99 }
100
101 public void setSeparator(char separator) {
102 this.separator = separator;
103 }
104
105 public void setQuote(char quote) {
106 this.quote = quote;
107 }
108
109 }