Skip to content

Commit 818380b

Browse files
committed
Revert "24"
This reverts commit 23d1fd2.
1 parent 23d1fd2 commit 818380b

23 files changed

Lines changed: 7584 additions & 2940 deletions

src/main/java/org/apache/commons/csv/CSVFormat.java

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,10 @@
4040
import java.util.Objects;
4141
import java.util.Set;
4242

43+
import org.apache.commons.codec.binary.Base64OutputStream;
44+
import org.apache.commons.io.IOUtils;
45+
import org.apache.commons.io.function.Uncheck;
46+
import org.apache.commons.io.output.AppendableOutputStream;
4347

4448
/**
4549
* Specifies the format of a CSV file for parsing and writing.
@@ -1638,7 +1642,19 @@ private void escape(final char c, final Appendable appendable) throws IOExceptio
16381642
* @param values the values to format
16391643
* @return the formatted values
16401644
*/
1645+
public String format(final Object... values) {
1646+
return Uncheck.get(() -> format_(values));
1647+
}
16411648

1649+
private String format_(final Object... values) throws IOException {
1650+
final StringWriter out = new StringWriter();
1651+
try (CSVPrinter csvPrinter = new CSVPrinter(out, this)) {
1652+
csvPrinter.printRecord(values);
1653+
final String res = out.toString();
1654+
final int len = recordSeparator != null ? res.length() - recordSeparator.length() : res.length();
1655+
return res.substring(0, len);
1656+
}
1657+
}
16421658

16431659
/**
16441660
* Gets whether duplicate names are allowed in the headers.
@@ -2034,6 +2050,9 @@ public CSVParser parse(final Reader reader) throws IOException {
20342050
* @return a printer to an output.
20352051
* @throws IOException thrown if the optional header cannot be printed.
20362052
*/
2053+
public CSVPrinter print(final Appendable out) throws IOException {
2054+
return new CSVPrinter(out, this);
2055+
}
20372056

20382057
/**
20392058
* Prints to the specified {@code File} with given {@code Charset}.
@@ -2048,7 +2067,31 @@ public CSVParser parse(final Reader reader) throws IOException {
20482067
* @throws IOException thrown if the optional header cannot be printed.
20492068
* @since 1.5
20502069
*/
2070+
@SuppressWarnings("resource")
2071+
public CSVPrinter print(final File out, final Charset charset) throws IOException {
2072+
// The writer will be closed when close() is called.
2073+
return new CSVPrinter(new OutputStreamWriter(new FileOutputStream(out), charset), this);
2074+
}
20512075

2076+
private void print(final InputStream inputStream, final Appendable out, final boolean newRecord) throws IOException {
2077+
// InputStream is never null here
2078+
// There is nothing to escape when quoting is used which is the default.
2079+
if (!newRecord) {
2080+
append(getDelimiterString(), out);
2081+
}
2082+
final boolean quoteCharacterSet = isQuoteCharacterSet();
2083+
if (quoteCharacterSet) {
2084+
append(getQuoteCharacter().charValue(), out);
2085+
}
2086+
// Stream the input to the output without reading or holding the whole value in memory.
2087+
// AppendableOutputStream cannot "close" an Appendable.
2088+
try (OutputStream outputStream = new Base64OutputStream(new AppendableOutputStream<>(out))) {
2089+
IOUtils.copy(inputStream, outputStream);
2090+
}
2091+
if (quoteCharacterSet) {
2092+
append(getQuoteCharacter().charValue(), out);
2093+
}
2094+
}
20522095

20532096
/**
20542097
* Prints the {@code value} as the next value on the line to {@code out}. The value will be escaped or encapsulated as needed. Useful when one wants to
@@ -2060,7 +2103,51 @@ public CSVParser parse(final Reader reader) throws IOException {
20602103
* @throws IOException If an I/O error occurs.
20612104
* @since 1.4
20622105
*/
2106+
public synchronized void print(final Object value, final Appendable out, final boolean newRecord) throws IOException {
2107+
// null values are considered empty
2108+
// Only call CharSequence.toString() if you have to, helps GC-free use cases.
2109+
CharSequence charSequence;
2110+
if (value == null) {
2111+
// https://issues.apache.org/jira/browse/CSV-203
2112+
if (null == nullString) {
2113+
charSequence = Constants.EMPTY;
2114+
} else if (QuoteMode.ALL == quoteMode) {
2115+
charSequence = quotedNullString;
2116+
} else {
2117+
charSequence = nullString;
2118+
}
2119+
} else if (value instanceof CharSequence) {
2120+
charSequence = (CharSequence) value;
2121+
} else if (value instanceof Reader) {
2122+
print((Reader) value, out, newRecord);
2123+
return;
2124+
} else if (value instanceof InputStream) {
2125+
print((InputStream) value, out, newRecord);
2126+
return;
2127+
} else {
2128+
charSequence = value.toString();
2129+
}
2130+
charSequence = getTrim() ? trim(charSequence) : charSequence;
2131+
print(value, charSequence, out, newRecord);
2132+
}
20632133

2134+
private synchronized void print(final Object object, final CharSequence value, final Appendable out, final boolean newRecord) throws IOException {
2135+
final int offset = 0;
2136+
final int len = value.length();
2137+
if (!newRecord) {
2138+
out.append(getDelimiterString());
2139+
}
2140+
if (object == null) {
2141+
out.append(value);
2142+
} else if (isQuoteCharacterSet()) {
2143+
// The original object is needed so can check for Number
2144+
printWithQuotes(object, value, out, newRecord);
2145+
} else if (isEscapeCharacterSet()) {
2146+
printWithEscapes(value, out);
2147+
} else {
2148+
out.append(value, offset, len);
2149+
}
2150+
}
20642151

20652152
/**
20662153
* Prints to the specified {@code Path} with given {@code Charset},
@@ -2076,7 +2163,26 @@ public CSVParser parse(final Reader reader) throws IOException {
20762163
* @throws IOException thrown if the optional header cannot be printed.
20772164
* @since 1.5
20782165
*/
2166+
@SuppressWarnings("resource")
2167+
public CSVPrinter print(final Path out, final Charset charset) throws IOException {
2168+
return print(Files.newBufferedWriter(out, charset));
2169+
}
20792170

2171+
private void print(final Reader reader, final Appendable out, final boolean newRecord) throws IOException {
2172+
// Reader is never null here
2173+
if (!newRecord) {
2174+
append(getDelimiterString(), out);
2175+
}
2176+
if (isQuoteCharacterSet()) {
2177+
printWithQuotes(reader, out);
2178+
} else if (isEscapeCharacterSet()) {
2179+
printWithEscapes(reader, out);
2180+
} else if (out instanceof Writer) {
2181+
IOUtils.copyLarge(reader, (Writer) out);
2182+
} else {
2183+
IOUtils.copy(reader, out);
2184+
}
2185+
}
20802186

20812187
/**
20822188
* Prints to the {@link System#out}.
@@ -2089,6 +2195,9 @@ public CSVParser parse(final Reader reader) throws IOException {
20892195
* @throws IOException thrown if the optional header cannot be printed.
20902196
* @since 1.5
20912197
*/
2198+
public CSVPrinter printer() throws IOException {
2199+
return new CSVPrinter(System.out, this);
2200+
}
20922201

20932202
/**
20942203
* Outputs the trailing delimiter (if set) followed by the record separator (if set).
@@ -2119,6 +2228,12 @@ public synchronized void println(final Appendable appendable) throws IOException
21192228
* @throws IOException If an I/O error occurs.
21202229
* @since 1.4
21212230
*/
2231+
public synchronized void printRecord(final Appendable appendable, final Object... values) throws IOException {
2232+
for (int i = 0; i < values.length; i++) {
2233+
print(values[i], appendable, i == 0);
2234+
}
2235+
println(appendable);
2236+
}
21222237

21232238
/*
21242239
* Note: Must only be called if escaping is enabled, otherwise can throw exceptions.

src/main/java/org/apache/commons/csv/CSVParser.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
import java.util.stream.Stream;
4848
import java.util.stream.StreamSupport;
4949

50+
import org.apache.commons.io.function.Uncheck;
5051

5152
/**
5253
* Parses CSV files according to the specified format.

0 commit comments

Comments
 (0)