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