Skip to content

Commit 7e47152

Browse files
alex270295garydgregory
authored andcommitted
[CSV-217] Add autoFlush option for CsvPrinter. Applying modified patch
This closes apache#24.
1 parent 10977ae commit 7e47152

5 files changed

Lines changed: 131 additions & 23 deletions

File tree

pom.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,12 @@ CSV files of various types.
3838
<version>4.12</version>
3939
<scope>test</scope>
4040
</dependency>
41+
<dependency>
42+
<groupId>org.mockito</groupId>
43+
<artifactId>mockito-all</artifactId>
44+
<version>1.9.5</version>
45+
<scope>test</scope>
46+
</dependency>
4147
<dependency>
4248
<groupId>commons-io</groupId>
4349
<artifactId>commons-io</artifactId>

src/changes/changes.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
</properties>
4040
<body>
4141
<release version="1.6" date="2017-MM-DD" description="Feature and bug fix release">
42+
<action issue="CSV-217" type="add" dev="ggregory" due-to="Korolyov Alexei">Add autoFlush option for CsvPrinter. PR #24.</action>
4243
</release>
4344
<release version="1.5" date="2017-09-03" description="Feature and bug fix release">
4445
<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>

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

Lines changed: 52 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,7 @@ public CSVFormat getFormat() {
242242
* @see Predefined#Default
243243
*/
244244
public static final CSVFormat DEFAULT = new CSVFormat(COMMA, DOUBLE_QUOTE_CHAR, null, null, null, false, true, CRLF,
245-
null, null, null, false, false, false, false, false);
245+
null, null, null, false, false, false, false, false, false);
246246

247247
/**
248248
* Excel file format (using a comma as the value delimiter). Note that the actual value delimiter used by Excel is
@@ -537,7 +537,7 @@ private static boolean isLineBreak(final Character c) {
537537
*/
538538
public static CSVFormat newFormat(final char delimiter) {
539539
return new CSVFormat(delimiter, null, null, null, null, false, false, null, null, null, null, false, false,
540-
false, false, false);
540+
false, false, false, false);
541541
}
542542

543543
/**
@@ -584,6 +584,8 @@ public static CSVFormat valueOf(final String format) {
584584

585585
private final boolean trim;
586586

587+
private final boolean autoFlush;
588+
587589
/**
588590
* Creates a customized CSV format.
589591
*
@@ -619,15 +621,16 @@ public static CSVFormat valueOf(final String format) {
619621
* TODO
620622
* @param trailingDelimiter
621623
* TODO
624+
* @param autoFlush
622625
* @throws IllegalArgumentException
623626
* if the delimiter is a line break character
624627
*/
625628
private CSVFormat(final char delimiter, final Character quoteChar, final QuoteMode quoteMode,
626-
final Character commentStart, final Character escape, final boolean ignoreSurroundingSpaces,
627-
final boolean ignoreEmptyLines, final String recordSeparator, final String nullString,
628-
final Object[] headerComments, final String[] header, final boolean skipHeaderRecord,
629-
final boolean allowMissingColumnNames, final boolean ignoreHeaderCase, final boolean trim,
630-
final boolean trailingDelimiter) {
629+
final Character commentStart, final Character escape, final boolean ignoreSurroundingSpaces,
630+
final boolean ignoreEmptyLines, final String recordSeparator, final String nullString,
631+
final Object[] headerComments, final String[] header, final boolean skipHeaderRecord,
632+
final boolean allowMissingColumnNames, final boolean ignoreHeaderCase, final boolean trim,
633+
final boolean trailingDelimiter, boolean autoFlush) {
631634
this.delimiter = delimiter;
632635
this.quoteCharacter = quoteChar;
633636
this.quoteMode = quoteMode;
@@ -644,6 +647,7 @@ private CSVFormat(final char delimiter, final Character quoteChar, final QuoteMo
644647
this.ignoreHeaderCase = ignoreHeaderCase;
645648
this.trailingDelimiter = trailingDelimiter;
646649
this.trim = trim;
650+
this.autoFlush = autoFlush;
647651
validate();
648652
}
649653

@@ -887,6 +891,16 @@ public boolean getTrim() {
887891
return trim;
888892
}
889893

894+
/**
895+
* Returns whether to flush on close.
896+
*
897+
* @return whether to flush on close.
898+
* @since 1.6
899+
*/
900+
public boolean getAutoFlush() {
901+
return autoFlush;
902+
}
903+
890904
@Override
891905
public int hashCode() {
892906
final int prime = 31;
@@ -1431,7 +1445,7 @@ public CSVFormat withAllowMissingColumnNames() {
14311445
public CSVFormat withAllowMissingColumnNames(final boolean allowMissingColumnNames) {
14321446
return new CSVFormat(delimiter, quoteCharacter, quoteMode, commentMarker, escapeCharacter,
14331447
ignoreSurroundingSpaces, ignoreEmptyLines, recordSeparator, nullString, headerComments, header,
1434-
skipHeaderRecord, allowMissingColumnNames, ignoreHeaderCase, trim, trailingDelimiter);
1448+
skipHeaderRecord, allowMissingColumnNames, ignoreHeaderCase, trim, trailingDelimiter, autoFlush);
14351449
}
14361450

14371451
/**
@@ -1466,7 +1480,7 @@ public CSVFormat withCommentMarker(final Character commentMarker) {
14661480
}
14671481
return new CSVFormat(delimiter, quoteCharacter, quoteMode, commentMarker, escapeCharacter,
14681482
ignoreSurroundingSpaces, ignoreEmptyLines, recordSeparator, nullString, headerComments, header,
1469-
skipHeaderRecord, allowMissingColumnNames, ignoreHeaderCase, trim, trailingDelimiter);
1483+
skipHeaderRecord, allowMissingColumnNames, ignoreHeaderCase, trim, trailingDelimiter, autoFlush);
14701484
}
14711485

14721486
/**
@@ -1484,7 +1498,7 @@ public CSVFormat withDelimiter(final char delimiter) {
14841498
}
14851499
return new CSVFormat(delimiter, quoteCharacter, quoteMode, commentMarker, escapeCharacter,
14861500
ignoreSurroundingSpaces, ignoreEmptyLines, recordSeparator, nullString, headerComments, header,
1487-
skipHeaderRecord, allowMissingColumnNames, ignoreHeaderCase, trim, trailingDelimiter);
1501+
skipHeaderRecord, allowMissingColumnNames, ignoreHeaderCase, trim, trailingDelimiter, autoFlush);
14881502
}
14891503

14901504
/**
@@ -1515,7 +1529,7 @@ public CSVFormat withEscape(final Character escape) {
15151529
}
15161530
return new CSVFormat(delimiter, quoteCharacter, quoteMode, commentMarker, escape, ignoreSurroundingSpaces,
15171531
ignoreEmptyLines, recordSeparator, nullString, headerComments, header, skipHeaderRecord,
1518-
allowMissingColumnNames, ignoreHeaderCase, trim, trailingDelimiter);
1532+
allowMissingColumnNames, ignoreHeaderCase, trim, trailingDelimiter, autoFlush);
15191533
}
15201534

15211535
/**
@@ -1670,7 +1684,7 @@ public CSVFormat withHeader(final ResultSetMetaData metaData) throws SQLExceptio
16701684
public CSVFormat withHeader(final String... header) {
16711685
return new CSVFormat(delimiter, quoteCharacter, quoteMode, commentMarker, escapeCharacter,
16721686
ignoreSurroundingSpaces, ignoreEmptyLines, recordSeparator, nullString, headerComments, header,
1673-
skipHeaderRecord, allowMissingColumnNames, ignoreHeaderCase, trim, trailingDelimiter);
1687+
skipHeaderRecord, allowMissingColumnNames, ignoreHeaderCase, trim, trailingDelimiter, autoFlush);
16741688
}
16751689

16761690
/**
@@ -1691,7 +1705,7 @@ public CSVFormat withHeader(final String... header) {
16911705
public CSVFormat withHeaderComments(final Object... headerComments) {
16921706
return new CSVFormat(delimiter, quoteCharacter, quoteMode, commentMarker, escapeCharacter,
16931707
ignoreSurroundingSpaces, ignoreEmptyLines, recordSeparator, nullString, headerComments, header,
1694-
skipHeaderRecord, allowMissingColumnNames, ignoreHeaderCase, trim, trailingDelimiter);
1708+
skipHeaderRecord, allowMissingColumnNames, ignoreHeaderCase, trim, trailingDelimiter, autoFlush);
16951709
}
16961710

16971711
/**
@@ -1716,7 +1730,7 @@ public CSVFormat withIgnoreEmptyLines() {
17161730
public CSVFormat withIgnoreEmptyLines(final boolean ignoreEmptyLines) {
17171731
return new CSVFormat(delimiter, quoteCharacter, quoteMode, commentMarker, escapeCharacter,
17181732
ignoreSurroundingSpaces, ignoreEmptyLines, recordSeparator, nullString, headerComments, header,
1719-
skipHeaderRecord, allowMissingColumnNames, ignoreHeaderCase, trim, trailingDelimiter);
1733+
skipHeaderRecord, allowMissingColumnNames, ignoreHeaderCase, trim, trailingDelimiter, autoFlush);
17201734
}
17211735

17221736
/**
@@ -1742,7 +1756,7 @@ public CSVFormat withIgnoreHeaderCase() {
17421756
public CSVFormat withIgnoreHeaderCase(final boolean ignoreHeaderCase) {
17431757
return new CSVFormat(delimiter, quoteCharacter, quoteMode, commentMarker, escapeCharacter,
17441758
ignoreSurroundingSpaces, ignoreEmptyLines, recordSeparator, nullString, headerComments, header,
1745-
skipHeaderRecord, allowMissingColumnNames, ignoreHeaderCase, trim, trailingDelimiter);
1759+
skipHeaderRecord, allowMissingColumnNames, ignoreHeaderCase, trim, trailingDelimiter, autoFlush);
17461760
}
17471761

17481762
/**
@@ -1767,7 +1781,7 @@ public CSVFormat withIgnoreSurroundingSpaces() {
17671781
public CSVFormat withIgnoreSurroundingSpaces(final boolean ignoreSurroundingSpaces) {
17681782
return new CSVFormat(delimiter, quoteCharacter, quoteMode, commentMarker, escapeCharacter,
17691783
ignoreSurroundingSpaces, ignoreEmptyLines, recordSeparator, nullString, headerComments, header,
1770-
skipHeaderRecord, allowMissingColumnNames, ignoreHeaderCase, trim, trailingDelimiter);
1784+
skipHeaderRecord, allowMissingColumnNames, ignoreHeaderCase, trim, trailingDelimiter, autoFlush);
17711785
}
17721786

17731787
/**
@@ -1786,7 +1800,7 @@ public CSVFormat withIgnoreSurroundingSpaces(final boolean ignoreSurroundingSpac
17861800
public CSVFormat withNullString(final String nullString) {
17871801
return new CSVFormat(delimiter, quoteCharacter, quoteMode, commentMarker, escapeCharacter,
17881802
ignoreSurroundingSpaces, ignoreEmptyLines, recordSeparator, nullString, headerComments, header,
1789-
skipHeaderRecord, allowMissingColumnNames, ignoreHeaderCase, trim, trailingDelimiter);
1803+
skipHeaderRecord, allowMissingColumnNames, ignoreHeaderCase, trim, trailingDelimiter, autoFlush);
17901804
}
17911805

17921806
/**
@@ -1817,7 +1831,7 @@ public CSVFormat withQuote(final Character quoteChar) {
18171831
}
18181832
return new CSVFormat(delimiter, quoteChar, quoteMode, commentMarker, escapeCharacter, ignoreSurroundingSpaces,
18191833
ignoreEmptyLines, recordSeparator, nullString, headerComments, header, skipHeaderRecord,
1820-
allowMissingColumnNames, ignoreHeaderCase, trim, trailingDelimiter);
1834+
allowMissingColumnNames, ignoreHeaderCase, trim, trailingDelimiter, autoFlush);
18211835
}
18221836

18231837
/**
@@ -1831,7 +1845,7 @@ public CSVFormat withQuote(final Character quoteChar) {
18311845
public CSVFormat withQuoteMode(final QuoteMode quoteModePolicy) {
18321846
return new CSVFormat(delimiter, quoteCharacter, quoteModePolicy, commentMarker, escapeCharacter,
18331847
ignoreSurroundingSpaces, ignoreEmptyLines, recordSeparator, nullString, headerComments, header,
1834-
skipHeaderRecord, allowMissingColumnNames, ignoreHeaderCase, trim, trailingDelimiter);
1848+
skipHeaderRecord, allowMissingColumnNames, ignoreHeaderCase, trim, trailingDelimiter, autoFlush);
18351849
}
18361850

18371851
/**
@@ -1869,7 +1883,7 @@ public CSVFormat withRecordSeparator(final char recordSeparator) {
18691883
public CSVFormat withRecordSeparator(final String recordSeparator) {
18701884
return new CSVFormat(delimiter, quoteCharacter, quoteMode, commentMarker, escapeCharacter,
18711885
ignoreSurroundingSpaces, ignoreEmptyLines, recordSeparator, nullString, headerComments, header,
1872-
skipHeaderRecord, allowMissingColumnNames, ignoreHeaderCase, trim, trailingDelimiter);
1886+
skipHeaderRecord, allowMissingColumnNames, ignoreHeaderCase, trim, trailingDelimiter, autoFlush);
18731887
}
18741888

18751889
/**
@@ -1896,7 +1910,7 @@ public CSVFormat withSkipHeaderRecord() {
18961910
public CSVFormat withSkipHeaderRecord(final boolean skipHeaderRecord) {
18971911
return new CSVFormat(delimiter, quoteCharacter, quoteMode, commentMarker, escapeCharacter,
18981912
ignoreSurroundingSpaces, ignoreEmptyLines, recordSeparator, nullString, headerComments, header,
1899-
skipHeaderRecord, allowMissingColumnNames, ignoreHeaderCase, trim, trailingDelimiter);
1913+
skipHeaderRecord, allowMissingColumnNames, ignoreHeaderCase, trim, trailingDelimiter, autoFlush);
19001914
}
19011915

19021916
/**
@@ -1921,7 +1935,7 @@ public CSVFormat withTrailingDelimiter() {
19211935
public CSVFormat withTrailingDelimiter(final boolean trailingDelimiter) {
19221936
return new CSVFormat(delimiter, quoteCharacter, quoteMode, commentMarker, escapeCharacter,
19231937
ignoreSurroundingSpaces, ignoreEmptyLines, recordSeparator, nullString, headerComments, header,
1924-
skipHeaderRecord, allowMissingColumnNames, ignoreHeaderCase, trim, trailingDelimiter);
1938+
skipHeaderRecord, allowMissingColumnNames, ignoreHeaderCase, trim, trailingDelimiter, autoFlush);
19251939
}
19261940

19271941
/**
@@ -1946,6 +1960,21 @@ public CSVFormat withTrim() {
19461960
public CSVFormat withTrim(final boolean trim) {
19471961
return new CSVFormat(delimiter, quoteCharacter, quoteMode, commentMarker, escapeCharacter,
19481962
ignoreSurroundingSpaces, ignoreEmptyLines, recordSeparator, nullString, headerComments, header,
1949-
skipHeaderRecord, allowMissingColumnNames, ignoreHeaderCase, trim, trailingDelimiter);
1963+
skipHeaderRecord, allowMissingColumnNames, ignoreHeaderCase, trim, trailingDelimiter, autoFlush);
1964+
}
1965+
1966+
/**
1967+
* Returns a new {@code CSVFormat} with whether to flush on close.
1968+
*
1969+
* @param autoFlush
1970+
* whether to flush on close.
1971+
*
1972+
* @return A new CSVFormat that is equal to this but with the specified autoFlush setting.
1973+
* @since 1.6
1974+
*/
1975+
public CSVFormat withAutoFlush(final boolean autoFlush) {
1976+
return new CSVFormat(delimiter, quoteCharacter, quoteMode, commentMarker, escapeCharacter,
1977+
ignoreSurroundingSpaces, ignoreEmptyLines, recordSeparator, nullString, headerComments, header,
1978+
skipHeaderRecord, allowMissingColumnNames, ignoreHeaderCase, trim, trailingDelimiter, autoFlush);
19501979
}
19511980
}

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

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,23 @@ public CSVPrinter(final Appendable out, final CSVFormat format) throws IOExcepti
8181

8282
@Override
8383
public void close() throws IOException {
84+
close(false);
85+
}
86+
87+
/**
88+
* Closes the underlying stream with an optional flush first.
89+
* @param flush whether to flush before the actual close.
90+
*
91+
* @throws IOException
92+
* If an I/O error occurs
93+
* @since 1.6
94+
*/
95+
public void close(boolean flush) throws IOException {
96+
if (flush || format.getAutoFlush()) {
97+
if (out instanceof Flushable) {
98+
((Flushable) out).flush();
99+
}
100+
}
84101
if (out instanceof Closeable) {
85102
((Closeable) out).close();
86103
}

src/test/java/org/apache/commons/csv/CSVPrinterTest.java

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,17 @@
2121
import static org.junit.Assert.assertArrayEquals;
2222
import static org.junit.Assert.assertEquals;
2323
import static org.junit.Assert.assertFalse;
24+
import static org.mockito.Mockito.mock;
25+
import static org.mockito.Mockito.never;
26+
import static org.mockito.Mockito.times;
27+
import static org.mockito.Mockito.verify;
2428

2529
import java.io.CharArrayWriter;
2630
import java.io.File;
2731
import java.io.IOException;
2832
import java.io.StringReader;
2933
import java.io.StringWriter;
34+
import java.io.Writer;
3035
import java.nio.charset.Charset;
3136
import java.nio.charset.StandardCharsets;
3237
import java.sql.BatchUpdateException;
@@ -1311,4 +1316,54 @@ public void testPrintRecordsWithEmptyVector() throws IOException {
13111316
}
13121317
}
13131318

1319+
@Test
1320+
public void testCloseWithFlushOn() throws IOException {
1321+
Writer writer = mock(Writer.class);
1322+
CSVFormat csvFormat = CSVFormat.DEFAULT;
1323+
CSVPrinter csvPrinter = new CSVPrinter(writer, csvFormat);
1324+
csvPrinter.close(true);
1325+
verify(writer, times(1)).flush();
1326+
}
1327+
1328+
@Test
1329+
public void testCloseWithFlushOff() throws IOException {
1330+
Writer writer = mock(Writer.class);
1331+
CSVFormat csvFormat = CSVFormat.DEFAULT;
1332+
CSVPrinter csvPrinter = new CSVPrinter(writer, csvFormat);
1333+
csvPrinter.close(false);
1334+
verify(writer, never()).flush();
1335+
verify(writer, times(1)).close();
1336+
}
1337+
1338+
@Test
1339+
public void testCloseBackwardCompatibility() throws IOException {
1340+
Writer writer = mock(Writer.class);
1341+
CSVFormat csvFormat = CSVFormat.DEFAULT;
1342+
try (CSVPrinter csvPrinter = new CSVPrinter(writer, csvFormat)) {
1343+
}
1344+
verify(writer, never()).flush();
1345+
verify(writer, times(1)).close();
1346+
}
1347+
1348+
@Test
1349+
public void testCloseWithCsvFormatAutoFlushOn() throws IOException {
1350+
System.out.println("start method");
1351+
Writer writer = mock(Writer.class);
1352+
CSVFormat csvFormat = CSVFormat.DEFAULT.withAutoFlush(true);
1353+
try (CSVPrinter csvPrinter = new CSVPrinter(writer, csvFormat)) {
1354+
}
1355+
verify(writer, times(1)).flush();
1356+
verify(writer, times(1)).close();
1357+
}
1358+
1359+
@Test
1360+
public void testCloseWithCsvFormatAutoFlushOff() throws IOException {
1361+
Writer writer = mock(Writer.class);
1362+
CSVFormat csvFormat = CSVFormat.DEFAULT.withAutoFlush(false);
1363+
try (CSVPrinter csvPrinter = new CSVPrinter(writer, csvFormat)) {
1364+
}
1365+
verify(writer, never()).flush();
1366+
verify(writer, times(1)).close();
1367+
}
1368+
13141369
}

0 commit comments

Comments
 (0)