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