1 package au.com.bytecode.opencsv;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 import java.io.*;
20 import java.math.BigDecimal;
21 import java.sql.*;
22 import java.text.SimpleDateFormat;
23 import java.util.List;
24
25
26
27
28
29
30
31 public class CSVWriter implements Closeable {
32
33 public static final int INITIAL_STRING_SIZE = 128;
34
35 private Writer rawWriter;
36
37 private PrintWriter pw;
38
39 private char separator;
40
41 private char quotechar;
42
43 private char escapechar;
44
45 private String lineEnd;
46
47
48 public static final char DEFAULT_ESCAPE_CHARACTER = '"';
49
50
51 public static final char DEFAULT_SEPARATOR = ',';
52
53
54
55
56
57 public static final char DEFAULT_QUOTE_CHARACTER = '"';
58
59
60 public static final char NO_QUOTE_CHARACTER = '\u0000';
61
62
63 public static final char NO_ESCAPE_CHARACTER = '\u0000';
64
65
66 public static final String DEFAULT_LINE_END = "\n";
67
68
69
70
71
72
73
74 public CSVWriter(Writer writer) {
75 this(writer, DEFAULT_SEPARATOR);
76 }
77
78
79
80
81
82
83
84
85
86 public CSVWriter(Writer writer, char separator) {
87 this(writer, separator, DEFAULT_QUOTE_CHARACTER);
88 }
89
90
91
92
93
94
95
96
97
98
99
100 public CSVWriter(Writer writer, char separator, char quotechar) {
101 this(writer, separator, quotechar, DEFAULT_ESCAPE_CHARACTER);
102 }
103
104
105
106
107
108
109
110
111
112
113
114
115
116 public CSVWriter(Writer writer, char separator, char quotechar, char escapechar) {
117 this(writer, separator, quotechar, escapechar, DEFAULT_LINE_END);
118 }
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133 public CSVWriter(Writer writer, char separator, char quotechar, String lineEnd) {
134 this(writer, separator, quotechar, DEFAULT_ESCAPE_CHARACTER, lineEnd);
135 }
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153 public CSVWriter(Writer writer, char separator, char quotechar, char escapechar, String lineEnd) {
154 this.rawWriter = writer;
155 this.pw = new PrintWriter(writer);
156 this.separator = separator;
157 this.quotechar = quotechar;
158 this.escapechar = escapechar;
159 this.lineEnd = lineEnd;
160 }
161
162
163
164
165
166
167
168
169
170 public void writeAll(List<String[]> allLines) {
171 for (String[] line : allLines) {
172 writeNext(line);
173 }
174 }
175
176 protected void writeColumnNames(ResultSetMetaData metadata)
177 throws SQLException {
178
179 int columnCount = metadata.getColumnCount();
180
181 String[] nextLine = new String[columnCount];
182 for (int i = 0; i < columnCount; i++) {
183 nextLine[i] = metadata.getColumnName(i + 1);
184 }
185 writeNext(nextLine);
186 }
187
188
189
190
191
192
193
194
195
196
197
198
199 public void writeAll(java.sql.ResultSet rs, boolean includeColumnNames) throws SQLException, IOException {
200
201 ResultSetMetaData metadata = rs.getMetaData();
202
203
204 if (includeColumnNames) {
205 writeColumnNames(metadata);
206 }
207
208 int columnCount = metadata.getColumnCount();
209
210 while (rs.next())
211 {
212 String[] nextLine = new String[columnCount];
213
214 for (int i = 0; i < columnCount; i++) {
215 nextLine[i] = getColumnValue(rs, metadata.getColumnType(i + 1), i + 1);
216 }
217
218 writeNext(nextLine);
219 }
220 }
221
222 private static String getColumnValue(ResultSet rs, int colType, int colIndex)
223 throws SQLException, IOException {
224
225 String value = "";
226
227 switch (colType)
228 {
229 case Types.BIT:
230 case Types.JAVA_OBJECT:
231 Object obj = rs.getObject(colIndex);
232 if (obj != null) {
233 value = String.valueOf(obj);
234 }
235 break;
236 case Types.BOOLEAN:
237 boolean b = rs.getBoolean(colIndex);
238 if (!rs.wasNull()) {
239 value = Boolean.valueOf(b).toString();
240 }
241 break;
242 case Types.CLOB:
243 Clob c = rs.getClob(colIndex);
244 if (c != null) {
245 value = read(c);
246 }
247 break;
248 case Types.BIGINT:
249 long lv = rs.getLong(colIndex);
250 if (!rs.wasNull()) {
251 value = Long.toString(lv);
252 }
253 break;
254 case Types.DECIMAL:
255 case Types.DOUBLE:
256 case Types.FLOAT:
257 case Types.REAL:
258 case Types.NUMERIC:
259 BigDecimal bd = rs.getBigDecimal(colIndex);
260 if (bd != null) {
261 value = bd.toString();
262 }
263 break;
264 case Types.INTEGER:
265 case Types.TINYINT:
266 case Types.SMALLINT:
267 int intValue = rs.getInt(colIndex);
268 if (!rs.wasNull()) {
269 value = Integer.toString(intValue);
270 }
271 break;
272 case Types.DATE:
273 java.sql.Date date = rs.getDate(colIndex);
274 if (date != null) {
275 SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MMM-yyyy");
276 value = dateFormat.format(date);
277 }
278 break;
279 case Types.TIME:
280 Time t = rs.getTime(colIndex);
281 if (t != null) {
282 value = t.toString();
283 }
284 break;
285 case Types.TIMESTAMP:
286 Timestamp tstamp = rs.getTimestamp(colIndex);
287 if (tstamp != null) {
288 SimpleDateFormat timeFormat = new SimpleDateFormat("dd-MMM-yyyy HH:mm:ss");
289 value = timeFormat.format(tstamp);
290 }
291 break;
292 case Types.LONGVARCHAR:
293 case Types.VARCHAR:
294 case Types.CHAR:
295 value = rs.getString(colIndex);
296 break;
297 default:
298 value = "";
299 }
300
301
302 if (value == null)
303 {
304 value = "";
305 }
306
307 return value;
308
309 }
310
311 private static String read(Clob c) throws SQLException, IOException
312 {
313 StringBuilder sb = new StringBuilder( (int) c.length());
314 Reader r = c.getCharacterStream();
315 char[] cbuf = new char[2048];
316 int n;
317 while ((n = r.read(cbuf, 0, cbuf.length)) != -1) {
318 if (n > 0) {
319 sb.append(cbuf, 0, n);
320 }
321 }
322 return sb.toString();
323 }
324
325
326
327
328
329
330
331
332 public void writeNext(String[] nextLine) {
333
334 if (nextLine == null)
335 return;
336
337 StringBuilder sb = new StringBuilder(INITIAL_STRING_SIZE);
338 for (int i = 0; i < nextLine.length; i++) {
339
340 if (i != 0) {
341 sb.append(separator);
342 }
343
344 String nextElement = nextLine[i];
345 if (nextElement == null)
346 continue;
347 if (quotechar != NO_QUOTE_CHARACTER)
348 sb.append(quotechar);
349
350 sb.append(stringContainsSpecialCharacters(nextElement) ? processLine(nextElement) : nextElement);
351
352 if (quotechar != NO_QUOTE_CHARACTER)
353 sb.append(quotechar);
354 }
355
356 sb.append(lineEnd);
357 pw.write(sb.toString());
358
359 }
360
361 private boolean stringContainsSpecialCharacters(String line) {
362 return line.indexOf(quotechar) != -1 || line.indexOf(escapechar) != -1;
363 }
364
365 protected StringBuilder processLine(String nextElement)
366 {
367 StringBuilder sb = new StringBuilder(INITIAL_STRING_SIZE);
368 for (int j = 0; j < nextElement.length(); j++) {
369 char nextChar = nextElement.charAt(j);
370 if (escapechar != NO_ESCAPE_CHARACTER && nextChar == quotechar) {
371 sb.append(escapechar).append(nextChar);
372 } else if (escapechar != NO_ESCAPE_CHARACTER && nextChar == escapechar) {
373 sb.append(escapechar).append(nextChar);
374 } else {
375 sb.append(nextChar);
376 }
377 }
378
379 return sb;
380 }
381
382
383
384
385
386
387 public void flush() throws IOException {
388
389 pw.flush();
390
391 }
392
393
394
395
396
397
398
399 public void close() throws IOException {
400 flush();
401 pw.close();
402 rawWriter.close();
403 }
404
405 }