1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements.  See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License.  You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 package org.apache.commons.io;
18 
19 import java.io.BufferedInputStream;
20 import java.io.BufferedReader;
21 import java.io.ByteArrayInputStream;
22 import java.io.ByteArrayOutputStream;
23 import java.io.CharArrayWriter;
24 import java.io.File;
25 import java.io.IOException;
26 import java.io.InputStream;
27 import java.io.InputStreamReader;
28 import java.io.OutputStream;
29 import java.io.OutputStreamWriter;
30 import java.io.PrintWriter;
31 import java.io.Reader;
32 import java.io.StringWriter;
33 import java.io.Writer;
34 import java.util.ArrayList;
35 import java.util.Collection;
36 import java.util.Iterator;
37 import java.util.List;
38 
39 /**
40  * General IO stream manipulation utilities.
41  * <p>
42  * This class provides static utility methods for input/output operations.
43  * <ul>
44  * <li>closeQuietly - these methods close a stream ignoring nulls and exceptions
45  * <li>toXxx/read - these methods read data from a stream
46  * <li>write - these methods write data to a stream
47  * <li>copy - these methods copy all the data from one stream to another
48  * <li>contentEquals - these methods compare the content of two streams
49  * </ul>
50  * <p>
51  * The byte-to-char methods and char-to-byte methods involve a conversion step.
52  * Two methods are provided in each case, one that uses the platform default
53  * encoding and the other which allows you to specify an encoding. You are
54  * encouraged to always specify an encoding because relying on the platform
55  * default can lead to unexpected results, for example when moving from
56  * development to production.
57  * <p>
58  * All the methods in this class that read a stream are buffered internally.
59  * This means that there is no cause to use a <code>BufferedInputStream</code>
60  * or <code>BufferedReader</code>. The default buffer size of 4K has been shown
61  * to be efficient in tests.
62  * <p>
63  * Wherever possible, the methods in this class do <em>not</em> flush or close
64  * the stream. This is to avoid making non-portable assumptions about the
65  * streams' origin and further use. Thus the caller is still responsible for
66  * closing streams after use.
67  * <p>
68  * Origin of code: Excalibur.
69  *
70  * @author Peter Donald
71  * @author Jeff Turner
72  * @author Matthew Hawthorne
73  * @author Stephen Colebourne
74  * @author Gareth Davis
75  * @author Ian Springer
76  * @author Niall Pemberton
77  * @author Sandy McArthur
78  * @version $Id: IOUtils.java 481854 2006-12-03 18:30:07Z scolebourne $
79  */
80 public class IOUtils {
81     // NOTE: This class is focussed on InputStream, OutputStream, Reader and
82     // Writer. Each method should take at least one of these as a parameter,
83     // or return one of them.
84 
85     /**
86      * The Unix directory separator character.
87      */
88     public static final char DIR_SEPARATOR_UNIX = '/';
89     /**
90      * The Windows directory separator character.
91      */
92     public static final char DIR_SEPARATOR_WINDOWS = '\\';
93     /**
94      * The system directory separator character.
95      */
96     public static final char DIR_SEPARATOR = File.separatorChar;
97     /**
98      * The Unix line separator string.
99      */
100     public static final String LINE_SEPARATOR_UNIX = "\n";
101     /**
102      * The Windows line separator string.
103      */
104     public static final String LINE_SEPARATOR_WINDOWS = "\r\n";
105     /**
106      * The system line separator string.
107      */
108     public static final String LINE_SEPARATOR;
109     static {
110         // avoid security issues
111         StringWriter buf = new StringWriter(4);
112         PrintWriter out = new PrintWriter(buf);
out.println()113         out.println();
114         LINE_SEPARATOR = buf.toString();
115     }
116 
117     /**
118      * The default buffer size to use.
119      */
120     private static final int DEFAULT_BUFFER_SIZE = 1024 * 4;
121 
122     /**
123      * Instances should NOT be constructed in standard programming.
124      */
IOUtils()125     public IOUtils() {
126         super();
127     }
128 
129     //-----------------------------------------------------------------------
130     /**
131      * Unconditionally close an <code>Reader</code>.
132      * <p>
133      * Equivalent to {@link Reader#close()}, except any exceptions will be ignored.
134      * This is typically used in finally blocks.
135      *
136      * @param input  the Reader to close, may be null or already closed
137      */
closeQuietly(Reader input)138     public static void closeQuietly(Reader input) {
139         try {
140             if (input != null) {
141                 input.close();
142             }
143         } catch (IOException ioe) {
144             // ignore
145         }
146     }
147 
148     /**
149      * Unconditionally close a <code>Writer</code>.
150      * <p>
151      * Equivalent to {@link Writer#close()}, except any exceptions will be ignored.
152      * This is typically used in finally blocks.
153      *
154      * @param output  the Writer to close, may be null or already closed
155      */
closeQuietly(Writer output)156     public static void closeQuietly(Writer output) {
157         try {
158             if (output != null) {
159                 output.close();
160             }
161         } catch (IOException ioe) {
162             // ignore
163         }
164     }
165 
166     /**
167      * Unconditionally close an <code>InputStream</code>.
168      * <p>
169      * Equivalent to {@link InputStream#close()}, except any exceptions will be ignored.
170      * This is typically used in finally blocks.
171      *
172      * @param input  the InputStream to close, may be null or already closed
173      */
closeQuietly(InputStream input)174     public static void closeQuietly(InputStream input) {
175         try {
176             if (input != null) {
177                 input.close();
178             }
179         } catch (IOException ioe) {
180             // ignore
181         }
182     }
183 
184     /**
185      * Unconditionally close an <code>OutputStream</code>.
186      * <p>
187      * Equivalent to {@link OutputStream#close()}, except any exceptions will be ignored.
188      * This is typically used in finally blocks.
189      *
190      * @param output  the OutputStream to close, may be null or already closed
191      */
closeQuietly(OutputStream output)192     public static void closeQuietly(OutputStream output) {
193         try {
194             if (output != null) {
195                 output.close();
196             }
197         } catch (IOException ioe) {
198             // ignore
199         }
200     }
201 
202     // read toByteArray
203     //-----------------------------------------------------------------------
204     /**
205      * Get the contents of an <code>InputStream</code> as a <code>byte[]</code>.
206      * <p>
207      * This method buffers the input internally, so there is no need to use a
208      * <code>BufferedInputStream</code>.
209      *
210      * @param input  the <code>InputStream</code> to read from
211      * @return the requested byte array
212      * @throws NullPointerException if the input is null
213      * @throws IOException if an I/O error occurs
214      */
toByteArray(InputStream input)215     public static byte[] toByteArray(InputStream input) throws IOException {
216         ByteArrayOutputStream output = new ByteArrayOutputStream();
217         copy(input, output);
218         return output.toByteArray();
219     }
220 
221     /**
222      * Get the contents of a <code>Reader</code> as a <code>byte[]</code>
223      * using the default character encoding of the platform.
224      * <p>
225      * This method buffers the input internally, so there is no need to use a
226      * <code>BufferedReader</code>.
227      *
228      * @param input  the <code>Reader</code> to read from
229      * @return the requested byte array
230      * @throws NullPointerException if the input is null
231      * @throws IOException if an I/O error occurs
232      */
toByteArray(Reader input)233     public static byte[] toByteArray(Reader input) throws IOException {
234         ByteArrayOutputStream output = new ByteArrayOutputStream();
235         copy(input, output);
236         return output.toByteArray();
237     }
238 
239     /**
240      * Get the contents of a <code>Reader</code> as a <code>byte[]</code>
241      * using the specified character encoding.
242      * <p>
243      * Character encoding names can be found at
244      * <a href="http://www.iana.org/assignments/character-sets">IANA</a>.
245      * <p>
246      * This method buffers the input internally, so there is no need to use a
247      * <code>BufferedReader</code>.
248      *
249      * @param input  the <code>Reader</code> to read from
250      * @param encoding  the encoding to use, null means platform default
251      * @return the requested byte array
252      * @throws NullPointerException if the input is null
253      * @throws IOException if an I/O error occurs
254      * @since Commons IO 1.1
255      */
toByteArray(Reader input, String encoding)256     public static byte[] toByteArray(Reader input, String encoding)
257             throws IOException {
258         ByteArrayOutputStream output = new ByteArrayOutputStream();
259         copy(input, output, encoding);
260         return output.toByteArray();
261     }
262 
263     /**
264      * Get the contents of a <code>String</code> as a <code>byte[]</code>
265      * using the default character encoding of the platform.
266      * <p>
267      * This is the same as {@link String#getBytes()}.
268      *
269      * @param input  the <code>String</code> to convert
270      * @return the requested byte array
271      * @throws NullPointerException if the input is null
272      * @throws IOException if an I/O error occurs (never occurs)
273      * @deprecated Use {@link String#getBytes()}
274      */
275     @Deprecated
toByteArray(String input)276     public static byte[] toByteArray(String input) throws IOException {
277         return input.getBytes();
278     }
279 
280     // read char[]
281     //-----------------------------------------------------------------------
282     /**
283      * Get the contents of an <code>InputStream</code> as a character array
284      * using the default character encoding of the platform.
285      * <p>
286      * This method buffers the input internally, so there is no need to use a
287      * <code>BufferedInputStream</code>.
288      *
289      * @param is  the <code>InputStream</code> to read from
290      * @return the requested character array
291      * @throws NullPointerException if the input is null
292      * @throws IOException if an I/O error occurs
293      * @since Commons IO 1.1
294      */
toCharArray(InputStream is)295     public static char[] toCharArray(InputStream is) throws IOException {
296         CharArrayWriter output = new CharArrayWriter();
297         copy(is, output);
298         return output.toCharArray();
299     }
300 
301     /**
302      * Get the contents of an <code>InputStream</code> as a character array
303      * using the specified character encoding.
304      * <p>
305      * Character encoding names can be found at
306      * <a href="http://www.iana.org/assignments/character-sets">IANA</a>.
307      * <p>
308      * This method buffers the input internally, so there is no need to use a
309      * <code>BufferedInputStream</code>.
310      *
311      * @param is  the <code>InputStream</code> to read from
312      * @param encoding  the encoding to use, null means platform default
313      * @return the requested character array
314      * @throws NullPointerException if the input is null
315      * @throws IOException if an I/O error occurs
316      * @since Commons IO 1.1
317      */
toCharArray(InputStream is, String encoding)318     public static char[] toCharArray(InputStream is, String encoding)
319             throws IOException {
320         CharArrayWriter output = new CharArrayWriter();
321         copy(is, output, encoding);
322         return output.toCharArray();
323     }
324 
325     /**
326      * Get the contents of a <code>Reader</code> as a character array.
327      * <p>
328      * This method buffers the input internally, so there is no need to use a
329      * <code>BufferedReader</code>.
330      *
331      * @param input  the <code>Reader</code> to read from
332      * @return the requested character array
333      * @throws NullPointerException if the input is null
334      * @throws IOException if an I/O error occurs
335      * @since Commons IO 1.1
336      */
toCharArray(Reader input)337     public static char[] toCharArray(Reader input) throws IOException {
338         CharArrayWriter sw = new CharArrayWriter();
339         copy(input, sw);
340         return sw.toCharArray();
341     }
342 
343     // read toString
344     //-----------------------------------------------------------------------
345     /**
346      * Get the contents of an <code>InputStream</code> as a String
347      * using the default character encoding of the platform.
348      * <p>
349      * This method buffers the input internally, so there is no need to use a
350      * <code>BufferedInputStream</code>.
351      *
352      * @param input  the <code>InputStream</code> to read from
353      * @return the requested String
354      * @throws NullPointerException if the input is null
355      * @throws IOException if an I/O error occurs
356      */
toString(InputStream input)357     public static String toString(InputStream input) throws IOException {
358         StringWriter sw = new StringWriter();
359         copy(input, sw);
360         return sw.toString();
361     }
362 
363     /**
364      * Get the contents of an <code>InputStream</code> as a String
365      * using the specified character encoding.
366      * <p>
367      * Character encoding names can be found at
368      * <a href="http://www.iana.org/assignments/character-sets">IANA</a>.
369      * <p>
370      * This method buffers the input internally, so there is no need to use a
371      * <code>BufferedInputStream</code>.
372      *
373      * @param input  the <code>InputStream</code> to read from
374      * @param encoding  the encoding to use, null means platform default
375      * @return the requested String
376      * @throws NullPointerException if the input is null
377      * @throws IOException if an I/O error occurs
378      */
toString(InputStream input, String encoding)379     public static String toString(InputStream input, String encoding)
380             throws IOException {
381         StringWriter sw = new StringWriter();
382         copy(input, sw, encoding);
383         return sw.toString();
384     }
385 
386     /**
387      * Get the contents of a <code>Reader</code> as a String.
388      * <p>
389      * This method buffers the input internally, so there is no need to use a
390      * <code>BufferedReader</code>.
391      *
392      * @param input  the <code>Reader</code> to read from
393      * @return the requested String
394      * @throws NullPointerException if the input is null
395      * @throws IOException if an I/O error occurs
396      */
toString(Reader input)397     public static String toString(Reader input) throws IOException {
398         StringWriter sw = new StringWriter();
399         copy(input, sw);
400         return sw.toString();
401     }
402 
403     /**
404      * Get the contents of a <code>byte[]</code> as a String
405      * using the default character encoding of the platform.
406      *
407      * @param input the byte array to read from
408      * @return the requested String
409      * @throws NullPointerException if the input is null
410      * @throws IOException if an I/O error occurs (never occurs)
411      * @deprecated Use {@link String#String(byte[])}
412      */
413     @Deprecated
toString(byte[] input)414     public static String toString(byte[] input) throws IOException {
415         return new String(input);
416     }
417 
418     /**
419      * Get the contents of a <code>byte[]</code> as a String
420      * using the specified character encoding.
421      * <p>
422      * Character encoding names can be found at
423      * <a href="http://www.iana.org/assignments/character-sets">IANA</a>.
424      *
425      * @param input the byte array to read from
426      * @param encoding  the encoding to use, null means platform default
427      * @return the requested String
428      * @throws NullPointerException if the input is null
429      * @throws IOException if an I/O error occurs (never occurs)
430      * @deprecated Use {@link String#String(byte[],String)}
431      */
432     @Deprecated
toString(byte[] input, String encoding)433     public static String toString(byte[] input, String encoding)
434             throws IOException {
435         if (encoding == null) {
436             return new String(input);
437         } else {
438             return new String(input, encoding);
439         }
440     }
441 
442     // readLines
443     //-----------------------------------------------------------------------
444     /**
445      * Get the contents of an <code>InputStream</code> as a list of Strings,
446      * one entry per line, using the default character encoding of the platform.
447      * <p>
448      * This method buffers the input internally, so there is no need to use a
449      * <code>BufferedInputStream</code>.
450      *
451      * @param input  the <code>InputStream</code> to read from, not null
452      * @return the list of Strings, never null
453      * @throws NullPointerException if the input is null
454      * @throws IOException if an I/O error occurs
455      * @since Commons IO 1.1
456      */
readLines(InputStream input)457     public static List<String> readLines(InputStream input) throws IOException {
458         InputStreamReader reader = new InputStreamReader(input);
459         return readLines(reader);
460     }
461 
462     /**
463      * Get the contents of an <code>InputStream</code> as a list of Strings,
464      * one entry per line, using the specified character encoding.
465      * <p>
466      * Character encoding names can be found at
467      * <a href="http://www.iana.org/assignments/character-sets">IANA</a>.
468      * <p>
469      * This method buffers the input internally, so there is no need to use a
470      * <code>BufferedInputStream</code>.
471      *
472      * @param input  the <code>InputStream</code> to read from, not null
473      * @param encoding  the encoding to use, null means platform default
474      * @return the list of Strings, never null
475      * @throws NullPointerException if the input is null
476      * @throws IOException if an I/O error occurs
477      * @since Commons IO 1.1
478      */
readLines(InputStream input, String encoding)479     public static List<String> readLines(InputStream input, String encoding) throws IOException {
480         if (encoding == null) {
481             return readLines(input);
482         } else {
483             InputStreamReader reader = new InputStreamReader(input, encoding);
484             return readLines(reader);
485         }
486     }
487 
488     /**
489      * Get the contents of a <code>Reader</code> as a list of Strings,
490      * one entry per line.
491      * <p>
492      * This method buffers the input internally, so there is no need to use a
493      * <code>BufferedReader</code>.
494      *
495      * @param input  the <code>Reader</code> to read from, not null
496      * @return the list of Strings, never null
497      * @throws NullPointerException if the input is null
498      * @throws IOException if an I/O error occurs
499      * @since Commons IO 1.1
500      */
readLines(Reader input)501     public static List<String> readLines(Reader input) throws IOException {
502         BufferedReader reader = new BufferedReader(input);
503         List<String> list = new ArrayList<String>();
504         String line = reader.readLine();
505         while (line != null) {
506             list.add(line);
507             line = reader.readLine();
508         }
509         return list;
510     }
511 
512     //-----------------------------------------------------------------------
513     /**
514      * Convert the specified string to an input stream, encoded as bytes
515      * using the default character encoding of the platform.
516      *
517      * @param input the string to convert
518      * @return an input stream
519      * @since Commons IO 1.1
520      */
toInputStream(String input)521     public static InputStream toInputStream(String input) {
522         byte[] bytes = input.getBytes();
523         return new ByteArrayInputStream(bytes);
524     }
525 
526     /**
527      * Convert the specified string to an input stream, encoded as bytes
528      * using the specified character encoding.
529      * <p>
530      * Character encoding names can be found at
531      * <a href="http://www.iana.org/assignments/character-sets">IANA</a>.
532      *
533      * @param input the string to convert
534      * @param encoding the encoding to use, null means platform default
535      * @throws IOException if the encoding is invalid
536      * @return an input stream
537      * @since Commons IO 1.1
538      */
toInputStream(String input, String encoding)539     public static InputStream toInputStream(String input, String encoding) throws IOException {
540         byte[] bytes = encoding != null ? input.getBytes(encoding) : input.getBytes();
541         return new ByteArrayInputStream(bytes);
542     }
543 
544     // write byte[]
545     //-----------------------------------------------------------------------
546     /**
547      * Writes bytes from a <code>byte[]</code> to an <code>OutputStream</code>.
548      *
549      * @param data  the byte array to write, do not modify during output,
550      * null ignored
551      * @param output  the <code>OutputStream</code> to write to
552      * @throws NullPointerException if output is null
553      * @throws IOException if an I/O error occurs
554      * @since Commons IO 1.1
555      */
write(byte[] data, OutputStream output)556     public static void write(byte[] data, OutputStream output)
557             throws IOException {
558         if (data != null) {
559             output.write(data);
560         }
561     }
562 
563     /**
564      * Writes bytes from a <code>byte[]</code> to chars on a <code>Writer</code>
565      * using the default character encoding of the platform.
566      * <p>
567      * This method uses {@link String#String(byte[])}.
568      *
569      * @param data  the byte array to write, do not modify during output,
570      * null ignored
571      * @param output  the <code>Writer</code> to write to
572      * @throws NullPointerException if output is null
573      * @throws IOException if an I/O error occurs
574      * @since Commons IO 1.1
575      */
write(byte[] data, Writer output)576     public static void write(byte[] data, Writer output) throws IOException {
577         if (data != null) {
578             output.write(new String(data));
579         }
580     }
581 
582     /**
583      * Writes bytes from a <code>byte[]</code> to chars on a <code>Writer</code>
584      * using the specified character encoding.
585      * <p>
586      * Character encoding names can be found at
587      * <a href="http://www.iana.org/assignments/character-sets">IANA</a>.
588      * <p>
589      * This method uses {@link String#String(byte[], String)}.
590      *
591      * @param data  the byte array to write, do not modify during output,
592      * null ignored
593      * @param output  the <code>Writer</code> to write to
594      * @param encoding  the encoding to use, null means platform default
595      * @throws NullPointerException if output is null
596      * @throws IOException if an I/O error occurs
597      * @since Commons IO 1.1
598      */
write(byte[] data, Writer output, String encoding)599     public static void write(byte[] data, Writer output, String encoding)
600             throws IOException {
601         if (data != null) {
602             if (encoding == null) {
603                 write(data, output);
604             } else {
605                 output.write(new String(data, encoding));
606             }
607         }
608     }
609 
610     // write char[]
611     //-----------------------------------------------------------------------
612     /**
613      * Writes chars from a <code>char[]</code> to a <code>Writer</code>
614      * using the default character encoding of the platform.
615      *
616      * @param data  the char array to write, do not modify during output,
617      * null ignored
618      * @param output  the <code>Writer</code> to write to
619      * @throws NullPointerException if output is null
620      * @throws IOException if an I/O error occurs
621      * @since Commons IO 1.1
622      */
write(char[] data, Writer output)623     public static void write(char[] data, Writer output) throws IOException {
624         if (data != null) {
625             output.write(data);
626         }
627     }
628 
629     /**
630      * Writes chars from a <code>char[]</code> to bytes on an
631      * <code>OutputStream</code>.
632      * <p>
633      * This method uses {@link String#String(char[])} and
634      * {@link String#getBytes()}.
635      *
636      * @param data  the char array to write, do not modify during output,
637      * null ignored
638      * @param output  the <code>OutputStream</code> to write to
639      * @throws NullPointerException if output is null
640      * @throws IOException if an I/O error occurs
641      * @since Commons IO 1.1
642      */
write(char[] data, OutputStream output)643     public static void write(char[] data, OutputStream output)
644             throws IOException {
645         if (data != null) {
646             output.write(new String(data).getBytes());
647         }
648     }
649 
650     /**
651      * Writes chars from a <code>char[]</code> to bytes on an
652      * <code>OutputStream</code> using the specified character encoding.
653      * <p>
654      * Character encoding names can be found at
655      * <a href="http://www.iana.org/assignments/character-sets">IANA</a>.
656      * <p>
657      * This method uses {@link String#String(char[])} and
658      * {@link String#getBytes(String)}.
659      *
660      * @param data  the char array to write, do not modify during output,
661      * null ignored
662      * @param output  the <code>OutputStream</code> to write to
663      * @param encoding  the encoding to use, null means platform default
664      * @throws NullPointerException if output is null
665      * @throws IOException if an I/O error occurs
666      * @since Commons IO 1.1
667      */
write(char[] data, OutputStream output, String encoding)668     public static void write(char[] data, OutputStream output, String encoding)
669             throws IOException {
670         if (data != null) {
671             if (encoding == null) {
672                 write(data, output);
673             } else {
674                 output.write(new String(data).getBytes(encoding));
675             }
676         }
677     }
678 
679     // write String
680     //-----------------------------------------------------------------------
681     /**
682      * Writes chars from a <code>String</code> to a <code>Writer</code>.
683      *
684      * @param data  the <code>String</code> to write, null ignored
685      * @param output  the <code>Writer</code> to write to
686      * @throws NullPointerException if output is null
687      * @throws IOException if an I/O error occurs
688      * @since Commons IO 1.1
689      */
write(String data, Writer output)690     public static void write(String data, Writer output) throws IOException {
691         if (data != null) {
692             output.write(data);
693         }
694     }
695 
696     /**
697      * Writes chars from a <code>String</code> to bytes on an
698      * <code>OutputStream</code> using the default character encoding of the
699      * platform.
700      * <p>
701      * This method uses {@link String#getBytes()}.
702      *
703      * @param data  the <code>String</code> to write, null ignored
704      * @param output  the <code>OutputStream</code> to write to
705      * @throws NullPointerException if output is null
706      * @throws IOException if an I/O error occurs
707      * @since Commons IO 1.1
708      */
write(String data, OutputStream output)709     public static void write(String data, OutputStream output)
710             throws IOException {
711         if (data != null) {
712             output.write(data.getBytes());
713         }
714     }
715 
716     /**
717      * Writes chars from a <code>String</code> to bytes on an
718      * <code>OutputStream</code> using the specified character encoding.
719      * <p>
720      * Character encoding names can be found at
721      * <a href="http://www.iana.org/assignments/character-sets">IANA</a>.
722      * <p>
723      * This method uses {@link String#getBytes(String)}.
724      *
725      * @param data  the <code>String</code> to write, null ignored
726      * @param output  the <code>OutputStream</code> to write to
727      * @param encoding  the encoding to use, null means platform default
728      * @throws NullPointerException if output is null
729      * @throws IOException if an I/O error occurs
730      * @since Commons IO 1.1
731      */
write(String data, OutputStream output, String encoding)732     public static void write(String data, OutputStream output, String encoding)
733             throws IOException {
734         if (data != null) {
735             if (encoding == null) {
736                 write(data, output);
737             } else {
738                 output.write(data.getBytes(encoding));
739             }
740         }
741     }
742 
743     // write StringBuffer
744     //-----------------------------------------------------------------------
745     /**
746      * Writes chars from a <code>StringBuffer</code> to a <code>Writer</code>.
747      *
748      * @param data  the <code>StringBuffer</code> to write, null ignored
749      * @param output  the <code>Writer</code> to write to
750      * @throws NullPointerException if output is null
751      * @throws IOException if an I/O error occurs
752      * @since Commons IO 1.1
753      */
write(StringBuffer data, Writer output)754     public static void write(StringBuffer data, Writer output)
755             throws IOException {
756         if (data != null) {
757             output.write(data.toString());
758         }
759     }
760 
761     /**
762      * Writes chars from a <code>StringBuffer</code> to bytes on an
763      * <code>OutputStream</code> using the default character encoding of the
764      * platform.
765      * <p>
766      * This method uses {@link String#getBytes()}.
767      *
768      * @param data  the <code>StringBuffer</code> to write, null ignored
769      * @param output  the <code>OutputStream</code> to write to
770      * @throws NullPointerException if output is null
771      * @throws IOException if an I/O error occurs
772      * @since Commons IO 1.1
773      */
write(StringBuffer data, OutputStream output)774     public static void write(StringBuffer data, OutputStream output)
775             throws IOException {
776         if (data != null) {
777             output.write(data.toString().getBytes());
778         }
779     }
780 
781     /**
782      * Writes chars from a <code>StringBuffer</code> to bytes on an
783      * <code>OutputStream</code> using the specified character encoding.
784      * <p>
785      * Character encoding names can be found at
786      * <a href="http://www.iana.org/assignments/character-sets">IANA</a>.
787      * <p>
788      * This method uses {@link String#getBytes(String)}.
789      *
790      * @param data  the <code>StringBuffer</code> to write, null ignored
791      * @param output  the <code>OutputStream</code> to write to
792      * @param encoding  the encoding to use, null means platform default
793      * @throws NullPointerException if output is null
794      * @throws IOException if an I/O error occurs
795      * @since Commons IO 1.1
796      */
write(StringBuffer data, OutputStream output, String encoding)797     public static void write(StringBuffer data, OutputStream output,
798             String encoding) throws IOException {
799         if (data != null) {
800             if (encoding == null) {
801                 write(data, output);
802             } else {
803                 output.write(data.toString().getBytes(encoding));
804             }
805         }
806     }
807 
808     // writeLines
809     //-----------------------------------------------------------------------
810     /**
811      * Writes the <code>toString()</code> value of each item in a collection to
812      * an <code>OutputStream</code> line by line, using the default character
813      * encoding of the platform and the specified line ending.
814      *
815      * @param lines  the lines to write, null entries produce blank lines
816      * @param lineEnding  the line separator to use, null is system default
817      * @param output  the <code>OutputStream</code> to write to, not null, not closed
818      * @throws NullPointerException if the output is null
819      * @throws IOException if an I/O error occurs
820      * @since Commons IO 1.1
821      */
writeLines(Collection<Object> lines, String lineEnding, OutputStream output)822     public static void writeLines(Collection<Object> lines, String lineEnding,
823             OutputStream output) throws IOException {
824         if (lines == null) {
825             return;
826         }
827         if (lineEnding == null) {
828             lineEnding = LINE_SEPARATOR;
829         }
830         for (Iterator<Object> it = lines.iterator(); it.hasNext(); ) {
831             Object line = it.next();
832             if (line != null) {
833                 output.write(line.toString().getBytes());
834             }
835             output.write(lineEnding.getBytes());
836         }
837     }
838 
839     /**
840      * Writes the <code>toString()</code> value of each item in a collection to
841      * an <code>OutputStream</code> line by line, using the specified character
842      * encoding and the specified line ending.
843      * <p>
844      * Character encoding names can be found at
845      * <a href="http://www.iana.org/assignments/character-sets">IANA</a>.
846      *
847      * @param lines  the lines to write, null entries produce blank lines
848      * @param lineEnding  the line separator to use, null is system default
849      * @param output  the <code>OutputStream</code> to write to, not null, not closed
850      * @param encoding  the encoding to use, null means platform default
851      * @throws NullPointerException if the output is null
852      * @throws IOException if an I/O error occurs
853      * @since Commons IO 1.1
854      */
writeLines(Collection<Object> lines, String lineEnding, OutputStream output, String encoding)855     public static void writeLines(Collection<Object> lines, String lineEnding,
856             OutputStream output, String encoding) throws IOException {
857         if (encoding == null) {
858             writeLines(lines, lineEnding, output);
859         } else {
860             if (lines == null) {
861                 return;
862             }
863             if (lineEnding == null) {
864                 lineEnding = LINE_SEPARATOR;
865             }
866             for (Iterator<Object> it = lines.iterator(); it.hasNext(); ) {
867                 Object line = it.next();
868                 if (line != null) {
869                     output.write(line.toString().getBytes(encoding));
870                 }
871                 output.write(lineEnding.getBytes(encoding));
872             }
873         }
874     }
875 
876     /**
877      * Writes the <code>toString()</code> value of each item in a collection to
878      * a <code>Writer</code> line by line, using the specified line ending.
879      *
880      * @param lines  the lines to write, null entries produce blank lines
881      * @param lineEnding  the line separator to use, null is system default
882      * @param writer  the <code>Writer</code> to write to, not null, not closed
883      * @throws NullPointerException if the input is null
884      * @throws IOException if an I/O error occurs
885      * @since Commons IO 1.1
886      */
writeLines(Collection<Object> lines, String lineEnding, Writer writer)887     public static void writeLines(Collection<Object> lines, String lineEnding,
888             Writer writer) throws IOException {
889         if (lines == null) {
890             return;
891         }
892         if (lineEnding == null) {
893             lineEnding = LINE_SEPARATOR;
894         }
895         for (Iterator<Object> it = lines.iterator(); it.hasNext(); ) {
896             Object line = it.next();
897             if (line != null) {
898                 writer.write(line.toString());
899             }
900             writer.write(lineEnding);
901         }
902     }
903 
904     // copy from InputStream
905     //-----------------------------------------------------------------------
906     /**
907      * Copy bytes from an <code>InputStream</code> to an
908      * <code>OutputStream</code>.
909      * <p>
910      * This method buffers the input internally, so there is no need to use a
911      * <code>BufferedInputStream</code>.
912      * <p>
913      * Large streams (over 2GB) will return a bytes copied value of
914      * <code>-1</code> after the copy has completed since the correct
915      * number of bytes cannot be returned as an int. For large streams
916      * use the <code>copyLarge(InputStream, OutputStream)</code> method.
917      *
918      * @param input  the <code>InputStream</code> to read from
919      * @param output  the <code>OutputStream</code> to write to
920      * @return the number of bytes copied
921      * @throws NullPointerException if the input or output is null
922      * @throws IOException if an I/O error occurs
923      * @throws ArithmeticException if the byte count is too large
924      * @since Commons IO 1.1
925      */
copy(InputStream input, OutputStream output)926     public static int copy(InputStream input, OutputStream output) throws IOException {
927         long count = copyLarge(input, output);
928         if (count > Integer.MAX_VALUE) {
929             return -1;
930         }
931         return (int) count;
932     }
933 
934     /**
935      * Copy bytes from a large (over 2GB) <code>InputStream</code> to an
936      * <code>OutputStream</code>.
937      * <p>
938      * This method buffers the input internally, so there is no need to use a
939      * <code>BufferedInputStream</code>.
940      *
941      * @param input  the <code>InputStream</code> to read from
942      * @param output  the <code>OutputStream</code> to write to
943      * @return the number of bytes copied
944      * @throws NullPointerException if the input or output is null
945      * @throws IOException if an I/O error occurs
946      * @since Commons IO 1.3
947      */
copyLarge(InputStream input, OutputStream output)948     public static long copyLarge(InputStream input, OutputStream output)
949             throws IOException {
950         byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
951         long count = 0;
952         int n = 0;
953         while (-1 != (n = input.read(buffer))) {
954             output.write(buffer, 0, n);
955             count += n;
956         }
957         return count;
958     }
959 
960     /**
961      * Copy bytes from an <code>InputStream</code> to chars on a
962      * <code>Writer</code> using the default character encoding of the platform.
963      * <p>
964      * This method buffers the input internally, so there is no need to use a
965      * <code>BufferedInputStream</code>.
966      * <p>
967      * This method uses {@link InputStreamReader}.
968      *
969      * @param input  the <code>InputStream</code> to read from
970      * @param output  the <code>Writer</code> to write to
971      * @throws NullPointerException if the input or output is null
972      * @throws IOException if an I/O error occurs
973      * @since Commons IO 1.1
974      */
copy(InputStream input, Writer output)975     public static void copy(InputStream input, Writer output)
976             throws IOException {
977         InputStreamReader in = new InputStreamReader(input);
978         copy(in, output);
979     }
980 
981     /**
982      * Copy bytes from an <code>InputStream</code> to chars on a
983      * <code>Writer</code> using the specified character encoding.
984      * <p>
985      * This method buffers the input internally, so there is no need to use a
986      * <code>BufferedInputStream</code>.
987      * <p>
988      * Character encoding names can be found at
989      * <a href="http://www.iana.org/assignments/character-sets">IANA</a>.
990      * <p>
991      * This method uses {@link InputStreamReader}.
992      *
993      * @param input  the <code>InputStream</code> to read from
994      * @param output  the <code>Writer</code> to write to
995      * @param encoding  the encoding to use, null means platform default
996      * @throws NullPointerException if the input or output is null
997      * @throws IOException if an I/O error occurs
998      * @since Commons IO 1.1
999      */
copy(InputStream input, Writer output, String encoding)1000     public static void copy(InputStream input, Writer output, String encoding)
1001             throws IOException {
1002         if (encoding == null) {
1003             copy(input, output);
1004         } else {
1005             InputStreamReader in = new InputStreamReader(input, encoding);
1006             copy(in, output);
1007         }
1008     }
1009 
1010     // copy from Reader
1011     //-----------------------------------------------------------------------
1012     /**
1013      * Copy chars from a <code>Reader</code> to a <code>Writer</code>.
1014      * <p>
1015      * This method buffers the input internally, so there is no need to use a
1016      * <code>BufferedReader</code>.
1017      * <p>
1018      * Large streams (over 2GB) will return a chars copied value of
1019      * <code>-1</code> after the copy has completed since the correct
1020      * number of chars cannot be returned as an int. For large streams
1021      * use the <code>copyLarge(Reader, Writer)</code> method.
1022      *
1023      * @param input  the <code>Reader</code> to read from
1024      * @param output  the <code>Writer</code> to write to
1025      * @return the number of characters copied
1026      * @throws NullPointerException if the input or output is null
1027      * @throws IOException if an I/O error occurs
1028      * @throws ArithmeticException if the character count is too large
1029      * @since Commons IO 1.1
1030      */
copy(Reader input, Writer output)1031     public static int copy(Reader input, Writer output) throws IOException {
1032         long count = copyLarge(input, output);
1033         if (count > Integer.MAX_VALUE) {
1034             return -1;
1035         }
1036         return (int) count;
1037     }
1038 
1039     /**
1040      * Copy chars from a large (over 2GB) <code>Reader</code> to a <code>Writer</code>.
1041      * <p>
1042      * This method buffers the input internally, so there is no need to use a
1043      * <code>BufferedReader</code>.
1044      *
1045      * @param input  the <code>Reader</code> to read from
1046      * @param output  the <code>Writer</code> to write to
1047      * @return the number of characters copied
1048      * @throws NullPointerException if the input or output is null
1049      * @throws IOException if an I/O error occurs
1050      * @since Commons IO 1.3
1051      */
copyLarge(Reader input, Writer output)1052     public static long copyLarge(Reader input, Writer output) throws IOException {
1053         char[] buffer = new char[DEFAULT_BUFFER_SIZE];
1054         long count = 0;
1055         int n = 0;
1056         while (-1 != (n = input.read(buffer))) {
1057             output.write(buffer, 0, n);
1058             count += n;
1059         }
1060         return count;
1061     }
1062 
1063     /**
1064      * Copy chars from a <code>Reader</code> to bytes on an
1065      * <code>OutputStream</code> using the default character encoding of the
1066      * platform, and calling flush.
1067      * <p>
1068      * This method buffers the input internally, so there is no need to use a
1069      * <code>BufferedReader</code>.
1070      * <p>
1071      * Due to the implementation of OutputStreamWriter, this method performs a
1072      * flush.
1073      * <p>
1074      * This method uses {@link OutputStreamWriter}.
1075      *
1076      * @param input  the <code>Reader</code> to read from
1077      * @param output  the <code>OutputStream</code> to write to
1078      * @throws NullPointerException if the input or output is null
1079      * @throws IOException if an I/O error occurs
1080      * @since Commons IO 1.1
1081      */
copy(Reader input, OutputStream output)1082     public static void copy(Reader input, OutputStream output)
1083             throws IOException {
1084         OutputStreamWriter out = new OutputStreamWriter(output);
1085         copy(input, out);
1086         // XXX Unless anyone is planning on rewriting OutputStreamWriter, we
1087         // have to flush here.
1088         out.flush();
1089     }
1090 
1091     /**
1092      * Copy chars from a <code>Reader</code> to bytes on an
1093      * <code>OutputStream</code> using the specified character encoding, and
1094      * calling flush.
1095      * <p>
1096      * This method buffers the input internally, so there is no need to use a
1097      * <code>BufferedReader</code>.
1098      * <p>
1099      * Character encoding names can be found at
1100      * <a href="http://www.iana.org/assignments/character-sets">IANA</a>.
1101      * <p>
1102      * Due to the implementation of OutputStreamWriter, this method performs a
1103      * flush.
1104      * <p>
1105      * This method uses {@link OutputStreamWriter}.
1106      *
1107      * @param input  the <code>Reader</code> to read from
1108      * @param output  the <code>OutputStream</code> to write to
1109      * @param encoding  the encoding to use, null means platform default
1110      * @throws NullPointerException if the input or output is null
1111      * @throws IOException if an I/O error occurs
1112      * @since Commons IO 1.1
1113      */
copy(Reader input, OutputStream output, String encoding)1114     public static void copy(Reader input, OutputStream output, String encoding)
1115             throws IOException {
1116         if (encoding == null) {
1117             copy(input, output);
1118         } else {
1119             OutputStreamWriter out = new OutputStreamWriter(output, encoding);
1120             copy(input, out);
1121             // XXX Unless anyone is planning on rewriting OutputStreamWriter,
1122             // we have to flush here.
1123             out.flush();
1124         }
1125     }
1126 
1127     // content equals
1128     //-----------------------------------------------------------------------
1129     /**
1130      * Compare the contents of two Streams to determine if they are equal or
1131      * not.
1132      * <p>
1133      * This method buffers the input internally using
1134      * <code>BufferedInputStream</code> if they are not already buffered.
1135      *
1136      * @param input1  the first stream
1137      * @param input2  the second stream
1138      * @return true if the content of the streams are equal or they both don't
1139      * exist, false otherwise
1140      * @throws NullPointerException if either input is null
1141      * @throws IOException if an I/O error occurs
1142      */
contentEquals(InputStream input1, InputStream input2)1143     public static boolean contentEquals(InputStream input1, InputStream input2)
1144             throws IOException {
1145         if (!(input1 instanceof BufferedInputStream)) {
1146             input1 = new BufferedInputStream(input1);
1147         }
1148         if (!(input2 instanceof BufferedInputStream)) {
1149             input2 = new BufferedInputStream(input2);
1150         }
1151 
1152         int ch = input1.read();
1153         while (-1 != ch) {
1154             int ch2 = input2.read();
1155             if (ch != ch2) {
1156                 return false;
1157             }
1158             ch = input1.read();
1159         }
1160 
1161         int ch2 = input2.read();
1162         return (ch2 == -1);
1163     }
1164 
1165     /**
1166      * Compare the contents of two Readers to determine if they are equal or
1167      * not.
1168      * <p>
1169      * This method buffers the input internally using
1170      * <code>BufferedReader</code> if they are not already buffered.
1171      *
1172      * @param input1  the first reader
1173      * @param input2  the second reader
1174      * @return true if the content of the readers are equal or they both don't
1175      * exist, false otherwise
1176      * @throws NullPointerException if either input is null
1177      * @throws IOException if an I/O error occurs
1178      * @since Commons IO 1.1
1179      */
contentEquals(Reader input1, Reader input2)1180     public static boolean contentEquals(Reader input1, Reader input2)
1181             throws IOException {
1182         if (!(input1 instanceof BufferedReader)) {
1183             input1 = new BufferedReader(input1);
1184         }
1185         if (!(input2 instanceof BufferedReader)) {
1186             input2 = new BufferedReader(input2);
1187         }
1188 
1189         int ch = input1.read();
1190         while (-1 != ch) {
1191             int ch2 = input2.read();
1192             if (ch != ch2) {
1193                 return false;
1194             }
1195             ch = input1.read();
1196         }
1197 
1198         int ch2 = input2.read();
1199         return (ch2 == -1);
1200     }
1201 
1202 }
1203