oms3.io.CSVPrinter Maven / Gradle / Ivy
/*
* $Id:$
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source
* distribution.
*/
package oms3.io;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.Writer;
/**
* Print values as a comma separated list.
*/
class CSVPrinter {
/** The place that the values get written. */
protected PrintWriter out;
/** True if we just began a new line. */
protected boolean newLine = true;
private CSVStrategy strategy = CSVStrategy.DEFAULT_STRATEGY;
/**
* Create a printer that will print values to the given
* stream. Character to byte conversion is done using
* the default character encoding. Comments will be
* written using the default comment character '#'.
*
* @param out stream to which to print.
*/
public CSVPrinter(OutputStream out) {
this.out = new PrintWriter(out);
}
/**
* Create a printer that will print values to the given
* stream. Comments will be
* written using the default comment character '#'.
*
* @param out stream to which to print.
*/
public CSVPrinter(Writer out) {
if (out instanceof PrintWriter) {
this.out = (PrintWriter) out;
} else {
this.out = new PrintWriter(out);
}
}
// ======================================================
// strategies
// ======================================================
/**
* Sets the specified CSV Strategy
*
* @return current instance of CSVParser to allow chained method calls
*/
public CSVPrinter setStrategy(CSVStrategy strategy) {
this.strategy = strategy;
return this;
}
/**
* Obtain the specified CSV Strategy
*
* @return strategy currently being used
*/
public CSVStrategy getStrategy() {
return this.strategy;
}
// ======================================================
// printing implementation
// ======================================================
/**
* Print the string as the last value on the line. The value
* will be quoted if needed.
*
* @param value value to be outputted.
*/
public void println(String value) {
print(value);
out.println();
out.flush();
newLine = true;
}
/**
* Output a blank line
*/
public void println() {
out.println();
out.flush();
newLine = true;
}
/**
* Print a single line of comma separated values.
* The values will be quoted if needed. Quotes and
* newLine characters will be escaped.
*
* @param values values to be outputted.
*/
public void println(String[] values) {
for (int i = 0; i < values.length; i++) {
print(values[i]);
}
out.println();
out.flush();
newLine = true;
}
/**
* Print several lines of comma separated values.
* The values will be quoted if needed. Quotes and
* newLine characters will be escaped.
*
* @param values values to be outputted.
*/
public void println(String[][] values) {
for (int i = 0; i < values.length; i++) {
println(values[i]);
}
if (values.length == 0) {
out.println();
}
out.flush();
newLine = true;
}
/**
* Put a comment among the comma separated values.
* Comments will always begin on a new line and occupy a
* least one full line. The character specified to star
* comments and a space will be inserted at the beginning of
* each new line in the comment.
*
* @param comment the comment to output
*/
public void printlnComment(String comment) {
if (this.strategy.isCommentingDisabled()) {
return;
}
if (!newLine) {
out.println();
}
out.print(this.strategy.getCommentStart());
out.print(' ');
for (int i = 0; i < comment.length(); i++) {
char c = comment.charAt(i);
switch (c) {
case '\r':
if (i + 1 < comment.length() && comment.charAt(i + 1) == '\n') {
i++;
}
// break intentionally excluded.
case '\n':
out.println();
out.print(this.strategy.getCommentStart());
out.print(' ');
break;
default:
out.print(c);
break;
}
}
out.println();
out.flush();
newLine = true;
}
/**
* Print the string as the next value on the line. The value
* will be quoted if needed.
*
* @param value value to be outputted.
*/
public void print(String value) {
boolean quote = false;
if (value.length() > 0) {
char c = value.charAt(0);
if (newLine && (c < '0' || (c > '9' && c < 'A') || (c > 'Z' && c < 'a') || (c > 'z'))) {
quote = true;
}
if (c == ' ' || c == '\f' || c == '\t') {
quote = true;
}
for (int i = 0; i < value.length(); i++) {
c = value.charAt(i);
if (c == '"' || c == this.strategy.getDelimiter() || c == '\n' || c == '\r') {
quote = true;
c = value.charAt(value.length() - 1);
break;
}
}
if (c == ' ' || c == '\f' || c == '\t') {
quote = true;
}
} else if (newLine) {
// always quote an empty token that is the first
// on the line, as it may be the only thing on the
// line. If it were not quoted in that case,
// an empty line has no tokens.
quote = true;
}
if (newLine) {
newLine = false;
} else {
out.print(this.strategy.getDelimiter());
}
if (quote) {
out.print(escapeAndQuote(value));
} else {
out.print(value);
}
out.flush();
}
/**
* Enclose the value in quotes and escape the quote
* and comma characters that are inside.
*
* @param value needs to be escaped and quoted
* @return the value, escaped and quoted
*/
private String escapeAndQuote(String value) {
// the initial count is for the preceding and trailing quotes
int count = 2;
for (int i = 0; i < value.length(); i++) {
switch (value.charAt(i)) {
case '\"':
case '\n':
case '\r':
case '\\':
count++;
break;
default:
break;
}
}
StringBuffer sb = new StringBuffer(value.length() + count);
sb.append(strategy.getEncapsulator());
for (int i = 0; i < value.length(); i++) {
char c = value.charAt(i);
if (c == strategy.getEncapsulator()) {
sb.append('\\').append(c);
continue;
}
switch (c) {
case '\n':
sb.append("\\n");
break;
case '\r':
sb.append("\\r");
break;
case '\\':
sb.append("\\\\");
break;
default:
sb.append(c);
}
}
sb.append(strategy.getEncapsulator());
return sb.toString();
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy