X-Git-Url: https://git.argeo.org/?a=blobdiff_plain;f=org.argeo.enterprise%2Fsrc%2Forg%2Fargeo%2Futil%2FCsvWriter.java;fp=org.argeo.enterprise%2Fsrc%2Forg%2Fargeo%2Futil%2FCsvWriter.java;h=c3b3a3ad7b43afa5989871fcaf0f223b1259a763;hb=fba24f5ac520b99b3ac75781c95f11c48ac6252f;hp=0000000000000000000000000000000000000000;hpb=3fbd05aa39ef235128e134fde8fd24167208e781;p=lgpl%2Fargeo-commons.git diff --git a/org.argeo.enterprise/src/org/argeo/util/CsvWriter.java b/org.argeo.enterprise/src/org/argeo/util/CsvWriter.java new file mode 100644 index 000000000..c3b3a3ad7 --- /dev/null +++ b/org.argeo.enterprise/src/org/argeo/util/CsvWriter.java @@ -0,0 +1,156 @@ +package org.argeo.util; + +import java.io.IOException; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.UnsupportedEncodingException; +import java.io.Writer; +import java.nio.charset.Charset; +import java.util.Iterator; +import java.util.List; + +/** Write in CSV format. */ +public class CsvWriter { + private final Writer out; + + private char separator = ','; + private char quote = '\"'; + + /** + * Creates a CSV writer. + * + * @param out the stream to write to. Caller is responsible for closing it. + * + * @deprecated Use {@link #CsvWriter(OutputStream, Charset)} instead. + * + */ + @Deprecated + public CsvWriter(OutputStream out) { + this.out = new OutputStreamWriter(out); + } + + /** + * Creates a CSV writer. + * + * @param out the stream to write to. Caller is responsible for closing it. + * @param encoding the encoding to use. + * + * @deprecated Use {@link #CsvWriter(OutputStream, Charset)} instead. + */ + @Deprecated + public CsvWriter(OutputStream out, String encoding) { + try { + this.out = new OutputStreamWriter(out, encoding); + } catch (UnsupportedEncodingException e) { + throw new IllegalArgumentException(e); + } + } + + /** + * Creates a CSV writer. + * + * @param out the stream to write to. Caller is responsible for closing it. + * @param charset the charset to use + */ + public CsvWriter(OutputStream out, Charset charset) { + this.out = new OutputStreamWriter(out, charset); + } + + /** + * Creates a CSV writer. + * + * @param out the stream to write to. Caller is responsible for closing it. + */ + public CsvWriter(Writer writer) { + this.out = writer; + } + + /** + * Write a CSV line. Also used to write a header if needed (this is transparent + * for the CSV writer): simply call it first, before writing the lines. + */ + public void writeLine(List tokens) { + try { + Iterator it = tokens.iterator(); + while (it.hasNext()) { + Object obj = it.next(); + writeToken(obj != null ? obj.toString() : null); + if (it.hasNext()) + out.write(separator); + } + out.write('\n'); + out.flush(); + } catch (IOException e) { + throw new RuntimeException("Could not write " + tokens, e); + } + } + + /** + * Write a CSV line. Also used to write a header if needed (this is transparent + * for the CSV writer): simply call it first, before writing the lines. + */ + public void writeLine(Object[] tokens) { + try { + for (int i = 0; i < tokens.length; i++) { + if (tokens[i] == null) { + writeToken(null); + } else { + writeToken(tokens[i].toString()); + } + if (i != (tokens.length - 1)) + out.write(separator); + } + out.write('\n'); + out.flush(); + } catch (IOException e) { + throw new RuntimeException("Could not write " + tokens, e); + } + } + + protected void writeToken(String token) throws IOException { + if (token == null) { + // TODO configure how to deal with null + out.write(""); + return; + } + // +2 for possible quotes, another +2 assuming there would be an already + // quoted string where quotes needs to be duplicated + // another +2 for safety + // we don't want to increase buffer size while writing + StringBuffer buf = new StringBuffer(token.length() + 6); + char[] arr = token.toCharArray(); + boolean shouldQuote = false; + for (char c : arr) { + if (!shouldQuote) { + if (c == separator) + shouldQuote = true; + if (c == '\n') + shouldQuote = true; + } + + if (c == quote) { + shouldQuote = true; + // duplicate quote + buf.append(quote); + } + + // generic case + buf.append(c); + } + + if (shouldQuote == true) + out.write(quote); + out.write(buf.toString()); + if (shouldQuote == true) + out.write(quote); + } + + public void setSeparator(char separator) { + this.separator = separator; + } + + public void setQuote(char quote) { + this.quote = quote; + } + +}