@@ -39,8 +39,10 @@ public final class CSVPrinter implements Flushable, Closeable {
3939 private final Appendable out ;
4040 private final CSVFormat format ;
4141
42- /** True if we just began a new record. */
43- private boolean newRecord = true ;
42+ /** 0 if we just began a new record. */
43+ private int newRecord = 0 ;
44+ /** true if first value is empty */
45+ private boolean firstEmpty ;
4446
4547 /**
4648 * Creates a printer that will print values to the given stream following the CSVFormat.
@@ -124,7 +126,7 @@ public void print(final Object value) throws IOException {
124126
125127 private void print (final Object object , final CharSequence value , final int offset , final int len )
126128 throws IOException {
127- if (! newRecord ) {
129+ if (newRecord > 0 ) {
128130 out .append (format .getDelimiter ());
129131 }
130132 if (format .isQuoteCharacterSet ()) {
@@ -135,7 +137,7 @@ private void print(final Object object, final CharSequence value, final int offs
135137 } else {
136138 out .append (value , offset , offset + len );
137139 }
138- newRecord = false ;
140+ newRecord ++ ;
139141 }
140142
141143 /*
@@ -208,18 +210,16 @@ private void printAndQuote(final Object object, final CharSequence value, final
208210 return ;
209211 case MINIMAL :
210212 if (len <= 0 ) {
211- // always quote an empty token that is the first
212- // on the line, as it may be the only thing on the
213- // line. If it were not quoted in that case,
214- // an empty line has no tokens.
215- if (newRecord ) {
216- quote = true ;
213+ // mark quotes may be required for first empty value
214+ if (newRecord == 0 ) {
215+ firstEmpty = true ;
216+ return ;
217217 }
218218 } else {
219219 char c = value .charAt (pos );
220220
221221 // TODO where did this rule come from?
222- if (newRecord && (c < '0' || (c > '9' && c < 'A' ) || (c > 'Z' && c < 'a' ) || (c > 'z' ))) {
222+ if (newRecord == 0 && (c < '0' || (c > '9' && c < 'A' ) || (c > 'Z' && c < 'a' ) || (c > 'z' ))) {
223223 quote = true ;
224224 } else if (c <= COMMENT ) {
225225 // Some other chars at the start of a value caused the parser to fail, so for now
@@ -307,7 +307,7 @@ public void printComment(final String comment) throws IOException {
307307 if (!format .isCommentMarkerSet ()) {
308308 return ;
309309 }
310- if (! newRecord ) {
310+ if (newRecord > 0 ) {
311311 println ();
312312 }
313313 out .append (format .getCommentMarker ().charValue ());
@@ -340,11 +340,20 @@ public void printComment(final String comment) throws IOException {
340340 * If an I/O error occurs
341341 */
342342 public void println () throws IOException {
343+ // if the line only contains an empty value
344+ if (newRecord == 1 && firstEmpty
345+ && (format .getQuoteMode () == null || format .getQuoteMode () == QuoteMode .MINIMAL )) {
346+ final char quoteChar = format .getQuoteCharacter ().charValue ();
347+ out .append (quoteChar );
348+ out .append (quoteChar );
349+ }
350+
343351 final String recordSeparator = format .getRecordSeparator ();
344352 if (recordSeparator != null ) {
345353 out .append (recordSeparator );
346354 }
347- newRecord = true ;
355+ newRecord = 0 ;
356+ firstEmpty = false ;
348357 }
349358
350359 /**
0 commit comments