diff --git a/src/main/java/com/fasterxml/jackson/dataformat/csv/CsvSchema.java b/src/main/java/com/fasterxml/jackson/dataformat/csv/CsvSchema.java index a513144..e7d9130 100644 --- a/src/main/java/com/fasterxml/jackson/dataformat/csv/CsvSchema.java +++ b/src/main/java/com/fasterxml/jackson/dataformat/csv/CsvSchema.java @@ -851,6 +851,9 @@ protected void _checkIndex(int index) { protected final int _escapeChar; protected final char[] _lineSeparator; + + /** CSV ends with a line separator ? Default is true */ + protected final boolean _endingLineSeparator; /** * @since 2.5 @@ -905,6 +908,7 @@ public CsvSchema(Column[] columns, int features, _quoteChar = quoteChar; _escapeChar = escapeChar; _lineSeparator = lineSeparator; + _endingLineSeparator = true; _nullValue = nullValue; _anyPropertyName = anyPropertyName; @@ -935,6 +939,29 @@ protected CsvSchema(Column[] columns, int features, _quoteChar = quoteChar; _escapeChar = escapeChar; _lineSeparator = lineSeparator; + _endingLineSeparator = true; + _arrayElementSeparator = arrayElementSeparator; + _nullValue = nullValue; + _columnsByName = columnsByName; + } + + /** + * Copy constructor used for creating variants using + * withXxx() methods. + */ + protected CsvSchema(Column[] columns, int features, + char columnSeparator, int quoteChar, int escapeChar, + char[] lineSeparator, boolean endingLineSeparator, int arrayElementSeparator, + char[] nullValue, + Map columnsByName) + { + _columns = columns; + _features = features; + _columnSeparator = columnSeparator; + _quoteChar = quoteChar; + _escapeChar = escapeChar; + _lineSeparator = lineSeparator; + _endingLineSeparator = endingLineSeparator; _arrayElementSeparator = arrayElementSeparator; _nullValue = nullValue; _columnsByName = columnsByName; @@ -953,6 +980,7 @@ protected CsvSchema(CsvSchema base, Column[] columns) _quoteChar = base._quoteChar; _escapeChar = base._escapeChar; _lineSeparator = base._lineSeparator; + _endingLineSeparator = true; _arrayElementSeparator = base._arrayElementSeparator; _nullValue = base._nullValue; _anyPropertyName = base._anyPropertyName; @@ -980,6 +1008,7 @@ protected CsvSchema(CsvSchema base, int features) { _quoteChar = base._quoteChar; _escapeChar = base._escapeChar; _lineSeparator = base._lineSeparator; + _endingLineSeparator = true; _arrayElementSeparator = base._arrayElementSeparator; _nullValue = base._nullValue; _anyPropertyName = base._anyPropertyName; @@ -1199,6 +1228,26 @@ public CsvSchema withLineSeparator(String sep) { _arrayElementSeparator, _nullValue, _columnsByName, _anyPropertyName); } + /** + * @return + */ + public CsvSchema withEndingLineSeparator() { + + return new CsvSchema(_columns, _features, + _columnSeparator, _quoteChar, _escapeChar, _lineSeparator, true, + _arrayElementSeparator, _nullValue, _columnsByName); + } + + /** + * @return + */ + public CsvSchema withoutEndingLineSeparator() { + + return new CsvSchema(_columns, _features, + _columnSeparator, _quoteChar, _escapeChar, _lineSeparator, false, + _arrayElementSeparator, _nullValue, _columnsByName); + } + /** * @since 2.5 */ @@ -1337,6 +1386,7 @@ public String getSchemaType() { public int getEscapeChar() { return _escapeChar; } public char[] getLineSeparator() { return _lineSeparator; } + public boolean getEndingLineSeparator() { return _endingLineSeparator; } /** * @return Null value defined, as char array, if one is defined to be recognized; Java null diff --git a/src/main/java/com/fasterxml/jackson/dataformat/csv/impl/CsvEncoder.java b/src/main/java/com/fasterxml/jackson/dataformat/csv/impl/CsvEncoder.java index e8119ab..266a902 100644 --- a/src/main/java/com/fasterxml/jackson/dataformat/csv/impl/CsvEncoder.java +++ b/src/main/java/com/fasterxml/jackson/dataformat/csv/impl/CsvEncoder.java @@ -53,6 +53,8 @@ public class CsvEncoder final protected int _cfgEscapeCharacter; final protected char[] _cfgLineSeparator; + + final protected boolean _cfgEndingLineSeparator; /** * @since 2.5 @@ -180,6 +182,7 @@ public CsvEncoder(IOContext ctxt, int csvFeatures, Writer out, CsvSchema schema) _cfgEscapeCharacter = schema.getEscapeChar(); _cfgLineSeparator = schema.getLineSeparator(); _cfgLineSeparatorLength = (_cfgLineSeparator == null) ? 0 : _cfgLineSeparator.length; + _cfgEndingLineSeparator = schema.getEndingLineSeparator(); _cfgNullValue = schema.getNullValueOrEmpty(); _columnCount = schema.size(); @@ -209,6 +212,7 @@ public CsvEncoder(CsvEncoder base, CsvSchema newSchema) _cfgEscapeCharacter = newSchema.getEscapeChar(); _cfgLineSeparator = newSchema.getLineSeparator(); _cfgLineSeparatorLength = _cfgLineSeparator.length; + _cfgEndingLineSeparator = newSchema.getEndingLineSeparator(); _cfgNullValue = newSchema.getNullValueOrEmpty(); _cfgMinSafeChar = _calcSafeChar(); _columnCount = newSchema.size(); @@ -439,6 +443,14 @@ public void endRow() throws IOException System.arraycopy(_cfgLineSeparator, 0, _outputBuffer, _outputTail, _cfgLineSeparatorLength); _outputTail += _cfgLineSeparatorLength; } + + /** + * + */ + public void removeEndingLineSeparator() { + + _outputTail -= _cfgLineSeparatorLength; + } /* /********************************************************** @@ -835,6 +847,9 @@ public void flush(boolean flushStream) throws IOException public void close(boolean autoClose) throws IOException { + if (!_cfgEndingLineSeparator) { + removeEndingLineSeparator(); + } _flushBuffer(); if (autoClose) { _out.close();