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 */
17package org.apache.commons.io;
18
19import java.io.BufferedInputStream;
20import java.io.BufferedReader;
21import java.io.ByteArrayInputStream;
22import java.io.ByteArrayOutputStream;
23import java.io.CharArrayWriter;
24import java.io.File;
25import java.io.IOException;
26import java.io.InputStream;
27import java.io.InputStreamReader;
28import java.io.OutputStream;
29import java.io.OutputStreamWriter;
30import java.io.PrintWriter;
31import java.io.Reader;
32import java.io.StringWriter;
33import java.io.Writer;
34import java.util.ArrayList;
35import java.util.Collection;
36import java.util.Iterator;
37import 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 */
80public 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);
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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
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     */
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     */
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     */
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     */
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     */
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     */
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
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
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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