Repository: commons-csv Updated Branches: refs/heads/master 10977ae1b -> 7e4715279
[CSV-217] Add autoFlush option for CsvPrinter. Applying modified patch This closes #24. Project: http://git-wip-us.apache.org/repos/asf/commons-csv/repo Commit: http://git-wip-us.apache.org/repos/asf/commons-csv/commit/7e471527 Tree: http://git-wip-us.apache.org/repos/asf/commons-csv/tree/7e471527 Diff: http://git-wip-us.apache.org/repos/asf/commons-csv/diff/7e471527 Branch: refs/heads/master Commit: 7e471527915cb0c73316c598fd02b71a56f2cf43 Parents: 10977ae Author: Korolyov Alexei <alex270...@yandex.ru> Authored: Mon Oct 9 13:22:53 2017 -0600 Committer: Gary Gregory <ggreg...@apache.org> Committed: Mon Oct 9 13:22:53 2017 -0600 ---------------------------------------------------------------------- pom.xml | 6 ++ src/changes/changes.xml | 1 + .../java/org/apache/commons/csv/CSVFormat.java | 75 ++++++++++++++------ .../java/org/apache/commons/csv/CSVPrinter.java | 17 +++++ .../org/apache/commons/csv/CSVPrinterTest.java | 55 ++++++++++++++ 5 files changed, 131 insertions(+), 23 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/commons-csv/blob/7e471527/pom.xml ---------------------------------------------------------------------- diff --git a/pom.xml b/pom.xml index 262bc17..8b13c17 100644 --- a/pom.xml +++ b/pom.xml @@ -39,6 +39,12 @@ CSV files of various types. <scope>test</scope> </dependency> <dependency> + <groupId>org.mockito</groupId> + <artifactId>mockito-all</artifactId> + <version>1.9.5</version> + <scope>test</scope> + </dependency> + <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.5</version> http://git-wip-us.apache.org/repos/asf/commons-csv/blob/7e471527/src/changes/changes.xml ---------------------------------------------------------------------- diff --git a/src/changes/changes.xml b/src/changes/changes.xml index bbfa930..b56b75f 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -39,6 +39,7 @@ </properties> <body> <release version="1.6" date="2017-MM-DD" description="Feature and bug fix release"> + <action issue="CSV-217" type="add" dev="ggregory" due-to="Korolyov Alexei">Add autoFlush option for CsvPrinter. PR #24.</action> </release> <release version="1.5" date="2017-09-03" description="Feature and bug fix release"> <action issue="CSV-203" type="fix" dev="ggregory" due-to="Richard Wheeldon, Kai Paroth">withNullString value is printed without quotes when QuoteMode.ALL is specified; add QuoteMode.ALL_NON_NULL. PR #17.</action> http://git-wip-us.apache.org/repos/asf/commons-csv/blob/7e471527/src/main/java/org/apache/commons/csv/CSVFormat.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/csv/CSVFormat.java b/src/main/java/org/apache/commons/csv/CSVFormat.java index 410c8fb..29b7c36 100644 --- a/src/main/java/org/apache/commons/csv/CSVFormat.java +++ b/src/main/java/org/apache/commons/csv/CSVFormat.java @@ -242,7 +242,7 @@ public final class CSVFormat implements Serializable { * @see Predefined#Default */ public static final CSVFormat DEFAULT = new CSVFormat(COMMA, DOUBLE_QUOTE_CHAR, null, null, null, false, true, CRLF, - null, null, null, false, false, false, false, false); + null, null, null, false, false, false, false, false, false); /** * Excel file format (using a comma as the value delimiter). Note that the actual value delimiter used by Excel is @@ -537,7 +537,7 @@ public final class CSVFormat implements Serializable { */ public static CSVFormat newFormat(final char delimiter) { return new CSVFormat(delimiter, null, null, null, null, false, false, null, null, null, null, false, false, - false, false, false); + false, false, false, false); } /** @@ -584,6 +584,8 @@ public final class CSVFormat implements Serializable { private final boolean trim; + private final boolean autoFlush; + /** * Creates a customized CSV format. * @@ -619,15 +621,16 @@ public final class CSVFormat implements Serializable { * TODO * @param trailingDelimiter * TODO + * @param autoFlush * @throws IllegalArgumentException * if the delimiter is a line break character */ private CSVFormat(final char delimiter, final Character quoteChar, final QuoteMode quoteMode, - final Character commentStart, final Character escape, final boolean ignoreSurroundingSpaces, - final boolean ignoreEmptyLines, final String recordSeparator, final String nullString, - final Object[] headerComments, final String[] header, final boolean skipHeaderRecord, - final boolean allowMissingColumnNames, final boolean ignoreHeaderCase, final boolean trim, - final boolean trailingDelimiter) { + final Character commentStart, final Character escape, final boolean ignoreSurroundingSpaces, + final boolean ignoreEmptyLines, final String recordSeparator, final String nullString, + final Object[] headerComments, final String[] header, final boolean skipHeaderRecord, + final boolean allowMissingColumnNames, final boolean ignoreHeaderCase, final boolean trim, + final boolean trailingDelimiter, boolean autoFlush) { this.delimiter = delimiter; this.quoteCharacter = quoteChar; this.quoteMode = quoteMode; @@ -644,6 +647,7 @@ public final class CSVFormat implements Serializable { this.ignoreHeaderCase = ignoreHeaderCase; this.trailingDelimiter = trailingDelimiter; this.trim = trim; + this.autoFlush = autoFlush; validate(); } @@ -887,6 +891,16 @@ public final class CSVFormat implements Serializable { return trim; } + /** + * Returns whether to flush on close. + * + * @return whether to flush on close. + * @since 1.6 + */ + public boolean getAutoFlush() { + return autoFlush; + } + @Override public int hashCode() { final int prime = 31; @@ -1431,7 +1445,7 @@ public final class CSVFormat implements Serializable { public CSVFormat withAllowMissingColumnNames(final boolean allowMissingColumnNames) { return new CSVFormat(delimiter, quoteCharacter, quoteMode, commentMarker, escapeCharacter, ignoreSurroundingSpaces, ignoreEmptyLines, recordSeparator, nullString, headerComments, header, - skipHeaderRecord, allowMissingColumnNames, ignoreHeaderCase, trim, trailingDelimiter); + skipHeaderRecord, allowMissingColumnNames, ignoreHeaderCase, trim, trailingDelimiter, autoFlush); } /** @@ -1466,7 +1480,7 @@ public final class CSVFormat implements Serializable { } return new CSVFormat(delimiter, quoteCharacter, quoteMode, commentMarker, escapeCharacter, ignoreSurroundingSpaces, ignoreEmptyLines, recordSeparator, nullString, headerComments, header, - skipHeaderRecord, allowMissingColumnNames, ignoreHeaderCase, trim, trailingDelimiter); + skipHeaderRecord, allowMissingColumnNames, ignoreHeaderCase, trim, trailingDelimiter, autoFlush); } /** @@ -1484,7 +1498,7 @@ public final class CSVFormat implements Serializable { } return new CSVFormat(delimiter, quoteCharacter, quoteMode, commentMarker, escapeCharacter, ignoreSurroundingSpaces, ignoreEmptyLines, recordSeparator, nullString, headerComments, header, - skipHeaderRecord, allowMissingColumnNames, ignoreHeaderCase, trim, trailingDelimiter); + skipHeaderRecord, allowMissingColumnNames, ignoreHeaderCase, trim, trailingDelimiter, autoFlush); } /** @@ -1515,7 +1529,7 @@ public final class CSVFormat implements Serializable { } return new CSVFormat(delimiter, quoteCharacter, quoteMode, commentMarker, escape, ignoreSurroundingSpaces, ignoreEmptyLines, recordSeparator, nullString, headerComments, header, skipHeaderRecord, - allowMissingColumnNames, ignoreHeaderCase, trim, trailingDelimiter); + allowMissingColumnNames, ignoreHeaderCase, trim, trailingDelimiter, autoFlush); } /** @@ -1670,7 +1684,7 @@ public final class CSVFormat implements Serializable { public CSVFormat withHeader(final String... header) { return new CSVFormat(delimiter, quoteCharacter, quoteMode, commentMarker, escapeCharacter, ignoreSurroundingSpaces, ignoreEmptyLines, recordSeparator, nullString, headerComments, header, - skipHeaderRecord, allowMissingColumnNames, ignoreHeaderCase, trim, trailingDelimiter); + skipHeaderRecord, allowMissingColumnNames, ignoreHeaderCase, trim, trailingDelimiter, autoFlush); } /** @@ -1691,7 +1705,7 @@ public final class CSVFormat implements Serializable { public CSVFormat withHeaderComments(final Object... headerComments) { return new CSVFormat(delimiter, quoteCharacter, quoteMode, commentMarker, escapeCharacter, ignoreSurroundingSpaces, ignoreEmptyLines, recordSeparator, nullString, headerComments, header, - skipHeaderRecord, allowMissingColumnNames, ignoreHeaderCase, trim, trailingDelimiter); + skipHeaderRecord, allowMissingColumnNames, ignoreHeaderCase, trim, trailingDelimiter, autoFlush); } /** @@ -1716,7 +1730,7 @@ public final class CSVFormat implements Serializable { public CSVFormat withIgnoreEmptyLines(final boolean ignoreEmptyLines) { return new CSVFormat(delimiter, quoteCharacter, quoteMode, commentMarker, escapeCharacter, ignoreSurroundingSpaces, ignoreEmptyLines, recordSeparator, nullString, headerComments, header, - skipHeaderRecord, allowMissingColumnNames, ignoreHeaderCase, trim, trailingDelimiter); + skipHeaderRecord, allowMissingColumnNames, ignoreHeaderCase, trim, trailingDelimiter, autoFlush); } /** @@ -1742,7 +1756,7 @@ public final class CSVFormat implements Serializable { public CSVFormat withIgnoreHeaderCase(final boolean ignoreHeaderCase) { return new CSVFormat(delimiter, quoteCharacter, quoteMode, commentMarker, escapeCharacter, ignoreSurroundingSpaces, ignoreEmptyLines, recordSeparator, nullString, headerComments, header, - skipHeaderRecord, allowMissingColumnNames, ignoreHeaderCase, trim, trailingDelimiter); + skipHeaderRecord, allowMissingColumnNames, ignoreHeaderCase, trim, trailingDelimiter, autoFlush); } /** @@ -1767,7 +1781,7 @@ public final class CSVFormat implements Serializable { public CSVFormat withIgnoreSurroundingSpaces(final boolean ignoreSurroundingSpaces) { return new CSVFormat(delimiter, quoteCharacter, quoteMode, commentMarker, escapeCharacter, ignoreSurroundingSpaces, ignoreEmptyLines, recordSeparator, nullString, headerComments, header, - skipHeaderRecord, allowMissingColumnNames, ignoreHeaderCase, trim, trailingDelimiter); + skipHeaderRecord, allowMissingColumnNames, ignoreHeaderCase, trim, trailingDelimiter, autoFlush); } /** @@ -1786,7 +1800,7 @@ public final class CSVFormat implements Serializable { public CSVFormat withNullString(final String nullString) { return new CSVFormat(delimiter, quoteCharacter, quoteMode, commentMarker, escapeCharacter, ignoreSurroundingSpaces, ignoreEmptyLines, recordSeparator, nullString, headerComments, header, - skipHeaderRecord, allowMissingColumnNames, ignoreHeaderCase, trim, trailingDelimiter); + skipHeaderRecord, allowMissingColumnNames, ignoreHeaderCase, trim, trailingDelimiter, autoFlush); } /** @@ -1817,7 +1831,7 @@ public final class CSVFormat implements Serializable { } return new CSVFormat(delimiter, quoteChar, quoteMode, commentMarker, escapeCharacter, ignoreSurroundingSpaces, ignoreEmptyLines, recordSeparator, nullString, headerComments, header, skipHeaderRecord, - allowMissingColumnNames, ignoreHeaderCase, trim, trailingDelimiter); + allowMissingColumnNames, ignoreHeaderCase, trim, trailingDelimiter, autoFlush); } /** @@ -1831,7 +1845,7 @@ public final class CSVFormat implements Serializable { public CSVFormat withQuoteMode(final QuoteMode quoteModePolicy) { return new CSVFormat(delimiter, quoteCharacter, quoteModePolicy, commentMarker, escapeCharacter, ignoreSurroundingSpaces, ignoreEmptyLines, recordSeparator, nullString, headerComments, header, - skipHeaderRecord, allowMissingColumnNames, ignoreHeaderCase, trim, trailingDelimiter); + skipHeaderRecord, allowMissingColumnNames, ignoreHeaderCase, trim, trailingDelimiter, autoFlush); } /** @@ -1869,7 +1883,7 @@ public final class CSVFormat implements Serializable { public CSVFormat withRecordSeparator(final String recordSeparator) { return new CSVFormat(delimiter, quoteCharacter, quoteMode, commentMarker, escapeCharacter, ignoreSurroundingSpaces, ignoreEmptyLines, recordSeparator, nullString, headerComments, header, - skipHeaderRecord, allowMissingColumnNames, ignoreHeaderCase, trim, trailingDelimiter); + skipHeaderRecord, allowMissingColumnNames, ignoreHeaderCase, trim, trailingDelimiter, autoFlush); } /** @@ -1896,7 +1910,7 @@ public final class CSVFormat implements Serializable { public CSVFormat withSkipHeaderRecord(final boolean skipHeaderRecord) { return new CSVFormat(delimiter, quoteCharacter, quoteMode, commentMarker, escapeCharacter, ignoreSurroundingSpaces, ignoreEmptyLines, recordSeparator, nullString, headerComments, header, - skipHeaderRecord, allowMissingColumnNames, ignoreHeaderCase, trim, trailingDelimiter); + skipHeaderRecord, allowMissingColumnNames, ignoreHeaderCase, trim, trailingDelimiter, autoFlush); } /** @@ -1921,7 +1935,7 @@ public final class CSVFormat implements Serializable { public CSVFormat withTrailingDelimiter(final boolean trailingDelimiter) { return new CSVFormat(delimiter, quoteCharacter, quoteMode, commentMarker, escapeCharacter, ignoreSurroundingSpaces, ignoreEmptyLines, recordSeparator, nullString, headerComments, header, - skipHeaderRecord, allowMissingColumnNames, ignoreHeaderCase, trim, trailingDelimiter); + skipHeaderRecord, allowMissingColumnNames, ignoreHeaderCase, trim, trailingDelimiter, autoFlush); } /** @@ -1946,6 +1960,21 @@ public final class CSVFormat implements Serializable { public CSVFormat withTrim(final boolean trim) { return new CSVFormat(delimiter, quoteCharacter, quoteMode, commentMarker, escapeCharacter, ignoreSurroundingSpaces, ignoreEmptyLines, recordSeparator, nullString, headerComments, header, - skipHeaderRecord, allowMissingColumnNames, ignoreHeaderCase, trim, trailingDelimiter); + skipHeaderRecord, allowMissingColumnNames, ignoreHeaderCase, trim, trailingDelimiter, autoFlush); + } + + /** + * Returns a new {@code CSVFormat} with whether to flush on close. + * + * @param autoFlush + * whether to flush on close. + * + * @return A new CSVFormat that is equal to this but with the specified autoFlush setting. + * @since 1.6 + */ + public CSVFormat withAutoFlush(final boolean autoFlush) { + return new CSVFormat(delimiter, quoteCharacter, quoteMode, commentMarker, escapeCharacter, + ignoreSurroundingSpaces, ignoreEmptyLines, recordSeparator, nullString, headerComments, header, + skipHeaderRecord, allowMissingColumnNames, ignoreHeaderCase, trim, trailingDelimiter, autoFlush); } } http://git-wip-us.apache.org/repos/asf/commons-csv/blob/7e471527/src/main/java/org/apache/commons/csv/CSVPrinter.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/csv/CSVPrinter.java b/src/main/java/org/apache/commons/csv/CSVPrinter.java index 96b24a4..49d9022 100644 --- a/src/main/java/org/apache/commons/csv/CSVPrinter.java +++ b/src/main/java/org/apache/commons/csv/CSVPrinter.java @@ -81,6 +81,23 @@ public final class CSVPrinter implements Flushable, Closeable { @Override public void close() throws IOException { + close(false); + } + + /** + * Closes the underlying stream with an optional flush first. + * @param flush whether to flush before the actual close. + * + * @throws IOException + * If an I/O error occurs + * @since 1.6 + */ + public void close(boolean flush) throws IOException { + if (flush || format.getAutoFlush()) { + if (out instanceof Flushable) { + ((Flushable) out).flush(); + } + } if (out instanceof Closeable) { ((Closeable) out).close(); } http://git-wip-us.apache.org/repos/asf/commons-csv/blob/7e471527/src/test/java/org/apache/commons/csv/CSVPrinterTest.java ---------------------------------------------------------------------- diff --git a/src/test/java/org/apache/commons/csv/CSVPrinterTest.java b/src/test/java/org/apache/commons/csv/CSVPrinterTest.java index 4a0ffbf..893675c 100644 --- a/src/test/java/org/apache/commons/csv/CSVPrinterTest.java +++ b/src/test/java/org/apache/commons/csv/CSVPrinterTest.java @@ -21,12 +21,17 @@ import static org.apache.commons.csv.Constants.CR; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; import java.io.CharArrayWriter; import java.io.File; import java.io.IOException; import java.io.StringReader; import java.io.StringWriter; +import java.io.Writer; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.sql.BatchUpdateException; @@ -1311,4 +1316,54 @@ public class CSVPrinterTest { } } + @Test + public void testCloseWithFlushOn() throws IOException { + Writer writer = mock(Writer.class); + CSVFormat csvFormat = CSVFormat.DEFAULT; + CSVPrinter csvPrinter = new CSVPrinter(writer, csvFormat); + csvPrinter.close(true); + verify(writer, times(1)).flush(); + } + + @Test + public void testCloseWithFlushOff() throws IOException { + Writer writer = mock(Writer.class); + CSVFormat csvFormat = CSVFormat.DEFAULT; + CSVPrinter csvPrinter = new CSVPrinter(writer, csvFormat); + csvPrinter.close(false); + verify(writer, never()).flush(); + verify(writer, times(1)).close(); + } + + @Test + public void testCloseBackwardCompatibility() throws IOException { + Writer writer = mock(Writer.class); + CSVFormat csvFormat = CSVFormat.DEFAULT; + try (CSVPrinter csvPrinter = new CSVPrinter(writer, csvFormat)) { + } + verify(writer, never()).flush(); + verify(writer, times(1)).close(); + } + + @Test + public void testCloseWithCsvFormatAutoFlushOn() throws IOException { + System.out.println("start method"); + Writer writer = mock(Writer.class); + CSVFormat csvFormat = CSVFormat.DEFAULT.withAutoFlush(true); + try (CSVPrinter csvPrinter = new CSVPrinter(writer, csvFormat)) { + } + verify(writer, times(1)).flush(); + verify(writer, times(1)).close(); + } + + @Test + public void testCloseWithCsvFormatAutoFlushOff() throws IOException { + Writer writer = mock(Writer.class); + CSVFormat csvFormat = CSVFormat.DEFAULT.withAutoFlush(false); + try (CSVPrinter csvPrinter = new CSVPrinter(writer, csvFormat)) { + } + verify(writer, never()).flush(); + verify(writer, times(1)).close(); + } + }