diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 722ed206..ce9a959a 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -38,6 +38,9 @@ Release Notes + + Make CSVPrinter.print(Object) GC-free. + Add shortcut method for using first record as header to CSVFormat Add withHeader(Class<? extends Enum>) to CSVFormat diff --git a/src/main/java/org/apache/commons/csv/CSVPrinter.java b/src/main/java/org/apache/commons/csv/CSVPrinter.java index dc23e1b9..cdd2c11e 100644 --- a/src/main/java/org/apache/commons/csv/CSVPrinter.java +++ b/src/main/java/org/apache/commons/csv/CSVPrinter.java @@ -121,15 +121,33 @@ public final class CSVPrinter implements Flushable, Closeable { */ public void print(final Object value) throws IOException { // null values are considered empty - String strValue; + // Only call CharSequence.toString() if you have to, helps GC-free use cases. + CharSequence charSequence; if (value == null) { final String nullString = format.getNullString(); - strValue = nullString == null ? Constants.EMPTY : nullString; + charSequence = nullString == null ? Constants.EMPTY : nullString; } else { - strValue = value.toString(); + charSequence = value instanceof CharSequence ? (CharSequence) value : value.toString(); } - strValue = format.getTrim() ? strValue.trim() : strValue; - this.print(value, strValue, 0, strValue.length()); + charSequence = format.getTrim() ? trim(charSequence) : charSequence; + this.print(value, charSequence, 0, charSequence.length()); + } + + private CharSequence trim(final CharSequence charSequence) { + if (charSequence instanceof String) { + return ((String) charSequence).trim(); + } + final int count = charSequence.length(); + int len = count; + int pos = 0; + + while ((pos < len) && (charSequence.charAt(pos) <= ' ')) { + pos++; + } + while ((pos < len) && (charSequence.charAt(len - 1) <= ' ')) { + len--; + } + return (pos > 0) || (len < count) ? charSequence.subSequence(pos, len) : charSequence; } private void print(final Object object, final CharSequence value, final int offset, final int len)