Skip to content

Commit e7434e5

Browse files
committed
Changed CSVPrinter to print to any Appendable and optimized the internals to avoid string copies
git-svn-id: https://svn.apache.org/repos/asf/commons/sandbox/csv/trunk@1297309 13f79535-47bb-0310-9956-ffa450edef68
1 parent e80b811 commit e7434e5

1 file changed

Lines changed: 36 additions & 46 deletions

File tree

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

Lines changed: 36 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -17,24 +17,21 @@
1717

1818
package org.apache.commons.csv;
1919

20+
import java.io.Flushable;
2021
import java.io.IOException;
21-
import java.io.Writer;
2222

2323
/**
2424
* Print values as a comma separated list.
2525
*/
2626
public class CSVPrinter {
2727

2828
/** The place that the values get written. */
29-
private final Writer out;
29+
private final Appendable out;
3030
private final CSVFormat format;
3131

3232
/** True if we just began a new line. */
3333
private boolean newLine = true;
3434

35-
/** Temporary buffer */
36-
private char[] buf = new char[0];
37-
3835
/**
3936
* Create a printer that will print values to the given stream following the CSVFormat.
4037
* <p/>
@@ -44,7 +41,7 @@ public class CSVPrinter {
4441
* @param out stream to which to print.
4542
* @param format describes the CSV variation.
4643
*/
47-
public CSVPrinter(Writer out, CSVFormat format) {
44+
public CSVPrinter(Appendable out, CSVFormat format) {
4845
this.out = out;
4946
this.format = format == null ? CSVFormat.DEFAULT : format;
5047
}
@@ -57,7 +54,7 @@ public CSVPrinter(Writer out, CSVFormat format) {
5754
* Output a blank line
5855
*/
5956
public void println() throws IOException {
60-
out.write(format.getLineSeparator());
57+
out.append(format.getLineSeparator());
6158
newLine = true;
6259
}
6360

@@ -67,10 +64,11 @@ public void println() throws IOException {
6764
* @throws IOException
6865
*/
6966
public void flush() throws IOException {
70-
out.flush();
67+
if (out instanceof Flushable) {
68+
((Flushable) out).flush();
69+
}
7170
}
7271

73-
7472
/**
7573
* Print a single line of comma separated values.
7674
* The values will be quoted if needed. Quotes and
@@ -103,8 +101,8 @@ public void printComment(String comment) throws IOException {
103101
if (!newLine) {
104102
println();
105103
}
106-
out.write(format.getCommentStart());
107-
out.write(' ');
104+
out.append(format.getCommentStart());
105+
out.append(' ');
108106
for (int i = 0; i < comment.length(); i++) {
109107
char c = comment.charAt(i);
110108
switch (c) {
@@ -115,38 +113,38 @@ public void printComment(String comment) throws IOException {
115113
// break intentionally excluded.
116114
case '\n':
117115
println();
118-
out.write(format.getCommentStart());
119-
out.write(' ');
116+
out.append(format.getCommentStart());
117+
out.append(' ');
120118
break;
121119
default:
122-
out.write(c);
120+
out.append(c);
123121
break;
124122
}
125123
}
126124
println();
127125
}
128126

129127

130-
private void print(char[] value, int offset, int len) throws IOException {
128+
private void print(CharSequence value, int offset, int len) throws IOException {
131129
if (format.isEncapsulating()) {
132130
printAndEncapsulate(value, offset, len);
133131
} else if (format.isEscaping()) {
134132
printAndEscape(value, offset, len);
135133
} else {
136134
printSep();
137-
out.write(value, offset, len);
135+
out.append(value, offset, offset + len);
138136
}
139137
}
140138

141139
void printSep() throws IOException {
142140
if (newLine) {
143141
newLine = false;
144142
} else {
145-
out.write(format.getDelimiter());
143+
out.append(format.getDelimiter());
146144
}
147145
}
148146

149-
void printAndEscape(char[] value, int offset, int len) throws IOException {
147+
void printAndEscape(CharSequence value, int offset, int len) throws IOException {
150148
int start = offset;
151149
int pos = offset;
152150
int end = offset + len;
@@ -157,21 +155,20 @@ void printAndEscape(char[] value, int offset, int len) throws IOException {
157155
char escape = format.getEscape();
158156

159157
while (pos < end) {
160-
char c = value[pos];
158+
char c = value.charAt(pos);
161159
if (c == '\r' || c == '\n' || c == delim || c == escape) {
162160
// write out segment up until this char
163-
int l = pos - start;
164-
if (l > 0) {
165-
out.write(value, start, l);
161+
if (pos > start) {
162+
out.append(value, start, pos);
166163
}
167164
if (c == '\n') {
168165
c = 'n';
169166
} else if (c == '\r') {
170167
c = 'r';
171168
}
172169

173-
out.write(escape);
174-
out.write(c);
170+
out.append(escape);
171+
out.append(c);
175172

176173
start = pos + 1; // start on the current char after this one
177174
}
@@ -180,13 +177,12 @@ void printAndEscape(char[] value, int offset, int len) throws IOException {
180177
}
181178

182179
// write last segment
183-
int l = pos - start;
184-
if (l > 0) {
185-
out.write(value, start, l);
180+
if (pos > start) {
181+
out.append(value, start, pos);
186182
}
187183
}
188184

189-
void printAndEncapsulate(char[] value, int offset, int len) throws IOException {
185+
void printAndEncapsulate(CharSequence value, int offset, int len) throws IOException {
190186
boolean first = newLine; // is this the first value on this line?
191187
boolean quote = false;
192188
int start = offset;
@@ -207,7 +203,7 @@ void printAndEncapsulate(char[] value, int offset, int len) throws IOException {
207203
quote = true;
208204
}
209205
} else {
210-
char c = value[pos];
206+
char c = value.charAt(pos);
211207

212208
// Hmmm, where did this rule come from?
213209
if (first
@@ -224,7 +220,7 @@ void printAndEncapsulate(char[] value, int offset, int len) throws IOException {
224220
quote = true;
225221
} else {
226222
while (pos < end) {
227-
c = value[pos];
223+
c = value.charAt(pos);
228224
if (c == '\n' || c == '\r' || c == encapsulator || c == delim) {
229225
quote = true;
230226
break;
@@ -234,7 +230,7 @@ void printAndEncapsulate(char[] value, int offset, int len) throws IOException {
234230

235231
if (!quote) {
236232
pos = end - 1;
237-
c = value[pos];
233+
c = value.charAt(pos);
238234
// if (c == ' ' || c == '\f' || c == '\t') {
239235
// Some other chars at the end caused the parser to fail, so for now
240236
// encapsulate if we end in anything less than ' '
@@ -247,22 +243,22 @@ void printAndEncapsulate(char[] value, int offset, int len) throws IOException {
247243

248244
if (!quote) {
249245
// no encapsulation needed - write out the original value
250-
out.write(value, offset, len);
246+
out.append(value, start, end);
251247
return;
252248
}
253249

254250
// we hit something that needed encapsulation
255-
out.write(encapsulator);
251+
out.append(encapsulator);
256252

257253
// Pick up where we left off: pos should be positioned on the first character that caused
258254
// the need for encapsulation.
259255
while (pos < end) {
260-
char c = value[pos];
256+
char c = value.charAt(pos);
261257
if (c == encapsulator) {
262258
// write out the chunk up until this point
263259

264260
// add 1 to the length to write out the encapsulator also
265-
out.write(value, start, pos - start + 1);
261+
out.append(value, start, pos + 1);
266262
// put the next starting position on the encapsulator so we will
267263
// write it out again with the next string (effectively doubling it)
268264
start = pos;
@@ -271,8 +267,8 @@ void printAndEncapsulate(char[] value, int offset, int len) throws IOException {
271267
}
272268

273269
// write the last segment
274-
out.write(value, start, pos - start);
275-
out.write(encapsulator);
270+
out.append(value, start, pos);
271+
out.append(encapsulator);
276272
}
277273

278274
/**
@@ -290,16 +286,10 @@ public void print(String value, boolean checkForEscape) throws IOException {
290286
if (!checkForEscape) {
291287
// write directly from string
292288
printSep();
293-
out.write(value);
294-
return;
295-
}
296-
297-
if (buf.length < value.length()) {
298-
buf = new char[value.length()];
289+
out.append(value);
290+
} else {
291+
print(value, 0, value.length());
299292
}
300-
301-
value.getChars(0, value.length(), buf, 0);
302-
print(buf, 0, value.length());
303293
}
304294

305295
/**

0 commit comments

Comments
 (0)