1717
1818package org .apache .commons .csv ;
1919
20+ import java .io .Flushable ;
2021import java .io .IOException ;
21- import java .io .Writer ;
2222
2323/**
2424 * Print values as a comma separated list.
2525 */
2626public 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