File D:\maven-qcr-plugin-testsunitaires\qcr4java\h2-1.3.170-sources\target\site\qc\lecode\tools\Csv.java.html

1 /*
2 * Copyright 2004-2011 H2 Group. Multiple-Licensed under the H2 License,
3 * Version 1.0, and under the Eclipse Public License, Version 1.0
4 * (http://h2database.com/html/license.html).
5 * Initial Developer: H2 Group
6 */
7 package org.h2.tools;
8
9 import java.io.BufferedInputStream;
10 import java.io.BufferedOutputStream;
11 import java.io.BufferedReader;
12 import java.io.BufferedWriter;
13 import java.io.IOException;
14 import java.io.InputStream;
15 import java.io.InputStreamReader;
16 import java.io.OutputStream;
17 import java.io.OutputStreamWriter;
18 import java.io.Reader;
19 import java.io.Writer;
20 import java.sql.Connection;
21 import java.sql.ResultSet;
22 import java.sql.ResultSetMetaData;
23 import java.sql.SQLException;
24 import java.sql.Statement;
25 import java.sql.Types;
26 import java.util.ArrayList;
27
28 import org.h2.constant.ErrorCode;
29 import org.h2.constant.SysProperties;
30 import org.h2.engine.Constants;
31 import org.h2.message.DbException;
32 import org.h2.store.fs.FileUtils;
33 import org.h2.util.IOUtils;
34 import org.h2.util.JdbcUtils;
35 import org.h2.util.New;
36 import org.h2.util.StringUtils;
37
38 /**
39 * A facility to read from and write to CSV (comma separated values) files. When
40 * reading, the BOM (the byte-order-mark) character 0xfeff at the beginning of
41 * the file is ignored.
42 *
43 * @author Thomas Mueller, Sylvain Cuaz
44 */
45 public class Csv implements SimpleRowSource {
46
47 private String[] columnNames;
48
49 private String characterSet = SysProperties.FILE_ENCODING;
50 private char escapeCharacter = '\"';
51 private char fieldDelimiter = '\"';
52 private char fieldSeparatorRead = ',';
53 private String fieldSeparatorWrite = ",";
54 private boolean caseSensitiveColumnNames;
55 private boolean preserveWhitespace;
56 private boolean writeColumnHeader = true;
57 private char lineComment;
58 private String lineSeparator = SysProperties.LINE_SEPARATOR;
59 private String nullString = "";
60
61 private String rowSeparatorWrite;
62 private String fileName;
63 private Reader input;
64 private char[] inputBuffer;
65 private int inputBufferPos;
66 private int inputBufferStart = -1;
67 private int inputBufferEnd;
68 private Writer output;
69 private boolean endOfLine, endOfFile;
70
71 /**
72 * Get a new object of this class.
73 *
74 * @deprecated use the public constructor instead
75 *
76 * @return the new instance
77 */
78 public static Csv getInstance() {
79 return new Csv();
80 }
81
82 private int writeResultSet(ResultSet rs) throws SQLException {
83 try {
84 int rows = 0;
85 ResultSetMetaData meta = rs.getMetaData();
86 int columnCount = meta.getColumnCount();
87 String[] row = new String[columnCount];
88 int[] sqlTypes = new int[columnCount];
89 for (int i = 0; i < columnCount; i++) {
90 row[i] = meta.getColumnLabel(i + 1);
91 sqlTypes[i] = meta.getColumnType(i + 1);
92 }
93 if (writeColumnHeader) {
94 writeRow(row);
95 }
96 while (rs.next()) {
97 for (int i = 0; i < columnCount; i++) {
98 Object o;
99 switch (sqlTypes[i]) {
100 case Types.DATE:
101 o = rs.getDate(i + 1);
102 break;
103 case Types.TIME:
104 o = rs.getTime(i + 1);
105 break;
106 case Types.TIMESTAMP:
107 o = rs.getTimestamp(i + 1);
108 break;
109 default:
110 o = rs.getString(i + 1);
111 }
112 row[i] = o == null ? null : o.toString();
113 }
114 writeRow(row);
115 rows++;
116 }
117 output.close();
118 return rows;
119 } catch (IOException e) {
120 throw DbException.convertIOException(e, null);
121 } finally {
122 close();
123 JdbcUtils.closeSilently(rs);
124 }
125 }
126
127 /**
128 * Writes the result set to a file in the CSV format.
129 *
130 * @param writer the writer
131 * @param rs the result set
132 * @return the number of rows written
133 * @throws SQLException
134 */
135 public int write(Writer writer, ResultSet rs) throws SQLException {
136 this.output = writer;
137 return writeResultSet(rs);
138 }
139
140 /**
141 * Writes the result set to a file in the CSV format. The result set is read
142 * using the following loop:
143 *
144 * <pre>
145 * while (rs.next()) {
146 * writeRow(row);
147 * }
148 * </pre>
149 *
150 * @param outputFileName the name of the csv file
151 * @param rs the result set - the result set must be positioned before the
152 * first row.
153 * @param charset the charset or null to use the system default charset
154 * (see system property file.encoding)
155 * @return the number of rows written
156 * @throws SQLException
157 */
158 public int write(String outputFileName, ResultSet rs, String charset) throws SQLException {
159 init(outputFileName, charset);
160 try {
161 initWrite();
162 return writeResultSet(rs);
163 } catch (IOException e) {
164 throw convertException("IOException writing " + outputFileName, e);
165 }
166 }
167
168 /**
169 * Writes the result set of a query to a file in the CSV format.
170 *
171 * @param conn the connection
172 * @param outputFileName the file name
173 * @param sql the query
174 * @param charset the charset or null to use the system default charset
175 * (see system property file.encoding)
176 * @return the number of rows written
177 * @throws SQLException
178 */
179 public int write(Connection conn, String outputFileName, String sql, String charset) throws SQLException {
180 Statement stat = conn.createStatement();
181 ResultSet rs = stat.executeQuery(sql);
182 int rows = write(outputFileName, rs, charset);
183 stat.close();
184 return rows;
185 }
186
187 /**
188 * Reads from the CSV file and returns a result set. The rows in the result
189 * set are created on demand, that means the file is kept open until all
190 * rows are read or the result set is closed.
191 * <br />
192 * If the columns are read from the CSV file, then the following rules are
193 * used: columns names that start with a letter or '_', and only
194 * contain letters, '_', and digits, are considered case insensitive
195 * and are converted to uppercase. Other column names are considered
196 * case sensitive (that means they need to be quoted when accessed).
197 *
198 * @param inputFileName the file name
199 * @param colNames or null if the column names should be read from the CSV
200 * file
201 * @param charset the charset or null to use the system default charset
202 * (see system property file.encoding)
203 * @return the result set
204 * @throws SQLException
205 */
206 public ResultSet read(String inputFileName, String[] colNames, String charset) throws SQLException {
207 init(inputFileName, charset);
208 try {
209 return readResultSet(colNames);
210 } catch (IOException e) {
211 throw convertException("IOException reading " + inputFileName, e);
212 }
213 }
214
215 /**
216 * Reads CSV data from a reader and returns a result set. The rows in the
217 * result set are created on demand, that means the reader is kept open
218 * until all rows are read or the result set is closed.
219 *
220 * @param reader the reader
221 * @param colNames or null if the column names should be read from the CSV file
222 * @return the result set
223 * @throws IOException
224 */
225 public ResultSet read(Reader reader, String[] colNames) throws IOException {
226 init(null, null);
227 this.input = reader;
228 return readResultSet(colNames);
229 }
230
231 private ResultSet readResultSet(String[] colNames) throws IOException {
232 this.columnNames = colNames;
233 initRead();
234 SimpleResultSet result = new SimpleResultSet(this);
235 makeColumnNamesUnique();
236 for (String columnName : columnNames) {
237 result.addColumn(columnName, Types.VARCHAR, Integer.MAX_VALUE, 0);
238 }
239 return result;
240 }
241
242 private void makeColumnNamesUnique() {
243 for (int i = 0; i < columnNames.length; i++) {
244 StringBuilder buff = new StringBuilder();
245 String n = columnNames[i];
246 if (n == null || n.length() == 0) {
247 buff.append('C').append(i + 1);
248 } else {
249 buff.append(n);
250 }
251 for (int j = 0; j < i; j++) {
252 String y = columnNames[j];
253 if (buff.toString().equals(y)) {
254 buff.append('1');
255 j = -1;
256 }
257 }
258 columnNames[i] = buff.toString();
259 }
260 }
261
262 private void init(String newFileName, String charset) {
263 this.fileName = newFileName;
264 if (charset != null) {
265 this.characterSet = charset;
266 }
267 }
268
269 private void initWrite() throws IOException {
270 if (output == null) {
271 try {
272 OutputStream out = FileUtils.newOutputStream(fileName, false);
273 out = new BufferedOutputStream(out, Constants.IO_BUFFER_SIZE);
274 output = new BufferedWriter(new OutputStreamWriter(out, characterSet));
275 } catch (Exception e) {
276 close();
277 throw DbException.convertToIOException(e);
278 }
279 }
280 }
281
282 private void writeRow(String[] values) throws IOException {
283 for (int i = 0; i < values.length; i++) {
284 if (i > 0) {
285 if (fieldSeparatorWrite != null) {
286 output.write(fieldSeparatorWrite);
287 }
288 }
289 String s = values[i];
290 if (s != null) {
291 if (escapeCharacter != 0) {
292 if (fieldDelimiter != 0) {
293 output.write(fieldDelimiter);
294 }
295 output.write(escape(s));
296 if (fieldDelimiter != 0) {
297 output.write(fieldDelimiter);
298 }
299 } else {
300 output.write(s);
301 }
302 } else if (nullString != null && nullString.length() > 0) {
303 output.write(nullString);
304 }
305 }
306 if (rowSeparatorWrite != null) {
307 output.write(rowSeparatorWrite);
308 }
309 output.write(lineSeparator);
310 }
311
312 private String escape(String data) {
313 if (data.indexOf(fieldDelimiter) < 0) {
314 if (escapeCharacter == fieldDelimiter || data.indexOf(escapeCharacter) < 0) {
315 return data;
316 }
317 }
318 int length = data.length();
319 StringBuilder buff = new StringBuilder(length);
320 for (int i = 0; i < length; i++) {
321 char ch = data.charAt(i);
322 if (ch == fieldDelimiter || ch == escapeCharacter) {
323 buff.append(escapeCharacter);
324 }
325 buff.append(ch);
326 }
327 return buff.toString();
328 }
329
330 private void initRead() throws IOException {
331 if (input == null) {
332 try {
333 InputStream in = FileUtils.newInputStream(fileName);
334 in = new BufferedInputStream(in, Constants.IO_BUFFER_SIZE);
335 input = new InputStreamReader(in, characterSet);
336 } catch (IOException e) {
337 close();
338 throw e;
339 }
340 }
341 if (!input.markSupported()) {
342 input = new BufferedReader(input);
343 }
344 input.mark(1);
345 int bom = input.read();
346 if (bom != 0xfeff) {
347 // Microsoft Excel compatibility
348 // ignore pseudo-BOM
349 input.reset();
350 }
351 inputBuffer = new char[Constants.IO_BUFFER_SIZE * 2];
352 if (columnNames == null) {
353 readHeader();
354 }
355 }
356
357 private void readHeader() throws IOException {
358 ArrayList<String> list = New.arrayList();
359 while (true) {
360 String v = readValue();
361 if (v == null) {
362 if (endOfLine) {
363 if (endOfFile || list.size() > 0) {
364 break;
365 }
366 } else {
367 v = "COLUMN" + list.size();
368 list.add(v);
369 }
370 } else {
371 if (v.length() == 0) {
372 v = "COLUMN" + list.size();
373 } else if (!caseSensitiveColumnNames && isSimpleColumnName(v)) {
374 v = v.toUpperCase();
375 }
376 list.add(v);
377 if (endOfLine) {
378 break;
379 }
380 }
381 }
382 columnNames = new String[list.size()];
383 list.toArray(columnNames);
384 }
385
386 private static boolean isSimpleColumnName(String columnName) {
387 for (int i = 0, length = columnName.length(); i < length; i++) {
388 char ch = columnName.charAt(i);
389 if (i == 0) {
390 if (ch != '_' && !Character.isLetter(ch)) {
391 return false;
392 }
393 } else {
394 if (ch != '_' && !Character.isLetterOrDigit(ch)) {
395 return false;
396 }
397 }
398 }
399 if (columnName.length() == 0) {
400 return false;
401 }
402 return true;
403 }
404
405 private void pushBack() {
406 inputBufferPos--;
407 }
408
409 private int readChar() throws IOException {
410 if (inputBufferPos >= inputBufferEnd) {
411 return readBuffer();
412 }
413 return inputBuffer[inputBufferPos++];
414 }
415
416 private int readBuffer() throws IOException {
417 if (endOfFile) {
418 return -1;
419 }
420 int keep;
421 if (inputBufferStart >= 0) {
422 keep = inputBufferPos - inputBufferStart;
423 if (keep > 0) {
424 char[] src = inputBuffer;
425 if (keep + Constants.IO_BUFFER_SIZE > src.length) {
426 inputBuffer = new char[src.length * 2];
427 }
428 System.arraycopy(src, inputBufferStart, inputBuffer, 0, keep);
429 }
430 inputBufferStart = 0;
431 } else {
432 keep = 0;
433 }
434 inputBufferPos = keep;
435 int len = input.read(inputBuffer, keep, Constants.IO_BUFFER_SIZE);
436 if (len == -1) {
437 // ensure bufferPos > bufferEnd
438 // even after pushBack
439 inputBufferEnd = -1024;
440 endOfFile = true;
441 // ensure the right number of characters are read
442 // in case the input buffer is still used
443 inputBufferPos++;
444 return -1;
445 }
446 inputBufferEnd = keep + len;
447 return inputBuffer[inputBufferPos++];
448 }
449
450 private String readValue() throws IOException {
451 endOfLine = false;
452 inputBufferStart = inputBufferPos;
453 while (true) {
454 int ch = readChar();
455 if (ch == fieldDelimiter) {
456 // delimited value
457 boolean containsEscape = false;
458 inputBufferStart = inputBufferPos;
459 int sep;
460 while (true) {
461 ch = readChar();
462 if (ch == fieldDelimiter) {
463 ch = readChar();
464 if (ch != fieldDelimiter) {
465 sep = 2;
466 break;
467 }
468 containsEscape = true;
469 } else if (ch == escapeCharacter) {
470 ch = readChar();
471 if (ch < 0) {
472 sep = 1;
473 break;
474 }
475 containsEscape = true;
476 } else if (ch < 0) {
477 sep = 1;
478 break;
479 }
480 }
481 String s = new String(inputBuffer, inputBufferStart, inputBufferPos - inputBufferStart - sep);
482 if (containsEscape) {
483 s = unEscape(s);
484 }
485 inputBufferStart = -1;
486 while (true) {
487 if (ch == fieldSeparatorRead) {
488 break;
489 } else if (ch == '\n' || ch < 0 || ch == '\r') {
490 endOfLine = true;
491 break;
492 } else if (ch == ' ' || ch == '\t') {
493 // ignore
494 } else {
495 pushBack();
496 break;
497 }
498 ch = readChar();
499 }
500 return s;
501 } else if (ch == '\n' || ch < 0 || ch == '\r') {
502 endOfLine = true;
503 return null;
504 } else if (ch == fieldSeparatorRead) {
505 // null
506 return null;
507 } else if (ch <= ' ') {
508 // ignore spaces
509 continue;
510 } else if (lineComment != 0 && ch == lineComment) {
511 // comment until end of line
512 inputBufferStart = -1;
513 while (true) {
514 ch = readChar();
515 if (ch == '\n' || ch < 0 || ch == '\r') {
516 break;
517 }
518 }
519 endOfLine = true;
520 return null;
521 } else {
522 // un-delimited value
523 while (true) {
524 ch = readChar();
525 if (ch == fieldSeparatorRead) {
526 break;
527 } else if (ch == '\n' || ch < 0 || ch == '\r') {
528 endOfLine = true;
529 break;
530 }
531 }
532 String s = new String(inputBuffer, inputBufferStart, inputBufferPos - inputBufferStart - 1);
533 if (!preserveWhitespace) {
534 s = s.trim();
535 }
536 inputBufferStart = -1;
537 // check un-delimited value for nullString
538 return readNull(s);
539 }
540 }
541 }
542
543 private String readNull(String s) {
544 return s.equals(nullString) ? null : s;
545 }
546
547 private String unEscape(String s) {
548 StringBuilder buff = new StringBuilder(s.length());
549 int start = 0;
550 char[] chars = null;
551 while (true) {
552 int idx = s.indexOf(escapeCharacter, start);
553 if (idx < 0) {
554 idx = s.indexOf(fieldDelimiter, start);
555 if (idx < 0) {
556 break;
557 }
558 }
559 if (chars == null) {
560 chars = s.toCharArray();
561 }
562 buff.append(chars, start, idx - start);
563 if (idx == s.length() - 1) {
564 start = s.length();
565 break;
566 }
567 buff.append(chars[idx + 1]);
568 start = idx + 2;
569 }
570 buff.append(s.substring(start));
571 return buff.toString();
572 }
573
574 /**
575 * INTERNAL
576 */
577 public Object[] readRow() throws SQLException {
578 if (input == null) {
579 return null;
580 }
581 String[] row = new String[columnNames.length];
582 try {
583 int i = 0;
584 while (true) {
585 String v = readValue();
586 if (v == null) {
587 if (endOfLine) {
588 if (i == 0) {
589 if (endOfFile) {
590 return null;
591 }
592 // empty line
593 continue;
594 }
595 break;
596 }
597 }
598 if (i < row.length) {
599 row[i++] = v;
600 }
601 if (endOfLine) {
602 break;
603 }
604 }
605 } catch (IOException e) {
606 throw convertException("IOException reading from " + fileName, e);
607 }
608 return row;
609 }
610
611 private static SQLException convertException(String message, Exception e) {
612 return DbException.get(ErrorCode.IO_EXCEPTION_1, e, message).getSQLException();
613 }
614
615 /**
616 * INTERNAL
617 */
618 public void close() {
619 IOUtils.closeSilently(input);
620 input = null;
621 IOUtils.closeSilently(output);
622 output = null;
623 }
624
625 /**
626 * INTERNAL
627 */
628 public void reset() throws SQLException {
629 throw new SQLException("Method is not supported", "CSV");
630 }
631
632 /**
633 * Override the field separator for writing. The default is ",".
634 *
635 * @param fieldSeparatorWrite the field separator
636 */
637 public void setFieldSeparatorWrite(String fieldSeparatorWrite) {
638 this.fieldSeparatorWrite = fieldSeparatorWrite;
639 }
640
641 /**
642 * Get the current field separator for writing.
643 *
644 * @return the field separator
645 */
646 public String getFieldSeparatorWrite() {
647 return fieldSeparatorWrite;
648 }
649
650 /**
651 * Override the case sensitive column names setting. The default is false.
652 * If enabled, the case of all column names is always preserved.
653 *
654 * @param caseSensitiveColumnNames whether column names are case sensitive
655 */
656 public void setCaseSensitiveColumnNames(boolean caseSensitiveColumnNames) {
657 this.caseSensitiveColumnNames = caseSensitiveColumnNames;
658 }
659
660 /**
661 * Get the current case sensitive column names setting.
662 *
663 * @return whether column names are case sensitive
664 */
665 public boolean getCaseSensitiveColumnNames() {
666 return caseSensitiveColumnNames;
667 }
668
669 /**
670 * Override the field separator for reading. The default is ','.
671 *
672 * @param fieldSeparatorRead the field separator
673 */
674 public void setFieldSeparatorRead(char fieldSeparatorRead) {
675 this.fieldSeparatorRead = fieldSeparatorRead;
676 }
677
678 /**
679 * Get the current field separator for reading.
680 *
681 * @return the field separator
682 */
683 public char getFieldSeparatorRead() {
684 return fieldSeparatorRead;
685 }
686
687 /**
688 * Get the current row separator for writing.
689 *
690 * @return the row separator
691 */
692 public String getRowSeparatorWrite() {
693 return rowSeparatorWrite;
694 }
695
696 /**
697 * Override the end-of-row marker for writing. The default is null. After
698 * writing the end-of-row marker, a line feed is written (\n or \r\n
699 * depending on the system settings).
700 *
701 * @param rowSeparatorWrite the row separator
702 */
703 public void setRowSeparatorWrite(String rowSeparatorWrite) {
704 this.rowSeparatorWrite = rowSeparatorWrite;
705 }
706
707 /**
708 * Set the line comment character. The default is character code 0 (line
709 * comments are disabled).
710 *
711 * @param lineCommentCharacter the line comment character
712 */
713 public void setLineCommentCharacter(char lineCommentCharacter) {
714 this.lineComment = lineCommentCharacter;
715 }
716
717 /**
718 * Get the line comment character.
719 *
720 * @return the line comment character, or 0 if disabled
721 */
722 public char getLineCommentCharacter() {
723 return lineComment;
724 }
725
726 /**
727 * Set the field delimiter. The default is " (a double quote).
728 * The value 0 means no field delimiter is used.
729 *
730 * @param fieldDelimiter the field delimiter
731 */
732 public void setFieldDelimiter(char fieldDelimiter) {
733 this.fieldDelimiter = fieldDelimiter;
734 }
735
736 /**
737 * Get the current field delimiter.
738 *
739 * @return the field delimiter
740 */
741 public char getFieldDelimiter() {
742 return fieldDelimiter;
743 }
744
745 /**
746 * Set the escape character. The escape character is used to escape the
747 * field delimiter. This is needed if the data contains the field delimiter.
748 * The default escape character is " (a double quote), which is the same as
749 * the field delimiter. If the field delimiter and the escape character are
750 * both " (double quote), and the data contains a double quote, then an
751 * additional double quote is added. Example:
752 * <pre>
753 * Data: He said "Hello".
754 * Escape character: "
755 * Field delimiter: "
756 * CSV file: "He said ""Hello""."
757 * </pre>
758 * If the field delimiter is a double quote and the escape character is a
759 * backslash, then escaping is done similar to Java (however, only the field
760 * delimiter is escaped). Example:
761 * <pre>
762 * Data: He said "Hello".
763 * Escape character: \
764 * Field delimiter: "
765 * CSV file: "He said \"Hello\"."
766 * </pre>
767 * The value 0 means no escape character is used.
768 *
769 * @param escapeCharacter the escape character
770 */
771 public void setEscapeCharacter(char escapeCharacter) {
772 this.escapeCharacter = escapeCharacter;
773 }
774
775 /**
776 * Get the current escape character.
777 *
778 * @return the escape character
779 */
780 public char getEscapeCharacter() {
781 return escapeCharacter;
782 }
783
784 /**
785 * Set the line separator.
786 *
787 * @param lineSeparator the line separator
788 */
789 public void setLineSeparator(String lineSeparator) {
790 this.lineSeparator = lineSeparator;
791 }
792
793 /**
794 * Get the current line separator.
795 *
796 * @return the line separator
797 */
798 public String getLineSeparator() {
799 return lineSeparator;
800 }
801
802 /**
803 * Set the value that represents NULL. It is only used for non-delimited
804 * values.
805 *
806 * @param nullString the null
807 */
808 public void setNullString(String nullString) {
809 this.nullString = nullString;
810 }
811
812 /**
813 * Get the current null string.
814 *
815 * @return the null string.
816 */
817 public String getNullString() {
818 return nullString;
819 }
820
821 /**
822 * Enable or disable preserving whitespace in unquoted text.
823 *
824 * @param value the new value for the setting
825 */
826 public void setPreserveWhitespace(boolean value) {
827 this.preserveWhitespace = value;
828 }
829
830 /**
831 * Whether whitespace in unquoted text is preserved.
832 *
833 * @return the current value for the setting
834 */
835 public boolean getPreserveWhitespace() {
836 return preserveWhitespace;
837 }
838
839 /**
840 * Enable or disable writing the column header.
841 *
842 * @param value the new value for the setting
843 */
844 public void setWriteColumnHeader(boolean value) {
845 this.writeColumnHeader = value;
846 }
847
848 /**
849 * Whether the column header is written.
850 *
851 * @return the current value for the setting
852 */
853 public boolean getWriteColumnHeader() {
854 return writeColumnHeader;
855 }
856
857 /**
858 * INTERNAL.
859 * Parse and set the CSV options.
860 *
861 * @param options the the options
862 * @return the character set
863 */
864 public String setOptions(String options) {
865 String charset = null;
866 String[] keyValuePairs = StringUtils.arraySplit(options, ' ', false);
867 for (String pair : keyValuePairs) {
868 if (pair.length() == 0) {
869 continue;
870 }
871 int index = pair.indexOf('=');
872 String key = StringUtils.trim(pair.substring(0, index), true, true, " ");
873 String value = pair.substring(index + 1);
874 char ch = value.length() == 0 ? 0 : value.charAt(0);
875 if (isParam(key, "escape", "esc", "escapeCharacter")) {
876 setEscapeCharacter(ch);
877 } else if (isParam(key, "fieldDelimiter", "fieldDelim")) {
878 setFieldDelimiter(ch);
879 } else if (isParam(key, "fieldSeparator", "fieldSep")) {
880 setFieldSeparatorRead(ch);
881 setFieldSeparatorWrite(value);
882 } else if (isParam(key, "lineComment", "lineCommentCharacter")) {
883 setLineCommentCharacter(ch);
884 } else if (isParam(key, "lineSeparator", "lineSep")) {
885 setLineSeparator(value);
886 } else if (isParam(key, "null", "nullString")) {
887 setNullString(value);
888 } else if (isParam(key, "rowSeparator", "rowSep")) {
889 setRowSeparatorWrite(value);
890 } else if (isParam(key, "charset", "characterSet")) {
891 charset = value;
892 } else if (isParam(key, "preserveWhitespace")) {
893 setPreserveWhitespace(Boolean.parseBoolean(value));
894 } else if (isParam(key, "writeColumnHeader")) {
895 setWriteColumnHeader(Boolean.parseBoolean(value));
896 } else if (isParam(key, "caseSensitiveColumnNames")) {
897 setCaseSensitiveColumnNames(Boolean.parseBoolean(value));
898 } else {
899 throw DbException.get(ErrorCode.FEATURE_NOT_SUPPORTED_1, key);
900 }
901 }
902 return charset;
903 }
904
905 private static boolean isParam(String key, String... values) {
906 for (String v : values) {
907 if (key.equalsIgnoreCase(v)) {
908 return true;
909 }
910 }
911 return false;
912 }
913
914 }
915