001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     * 
009     *      http://www.apache.org/licenses/LICENSE-2.0
010     * 
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    package org.apache.commons.io;
018    
019    import java.io.BufferedInputStream;
020    import java.io.BufferedReader;
021    import java.io.ByteArrayInputStream;
022    import java.io.CharArrayWriter;
023    import java.io.File;
024    import java.io.IOException;
025    import java.io.InputStream;
026    import java.io.InputStreamReader;
027    import java.io.OutputStream;
028    import java.io.OutputStreamWriter;
029    import java.io.PrintWriter;
030    import java.io.Reader;
031    import java.io.StringWriter;
032    import java.io.Writer;
033    import java.util.ArrayList;
034    import java.util.Collection;
035    import java.util.Iterator;
036    import java.util.List;
037    
038    import org.apache.commons.io.output.ByteArrayOutputStream;
039    
040    /**
041     * General IO stream manipulation utilities.
042     * <p>
043     * This class provides static utility methods for input/output operations.
044     * <ul>
045     * <li>closeQuietly - these methods close a stream ignoring nulls and exceptions
046     * <li>toXxx/read - these methods read data from a stream
047     * <li>write - these methods write data to a stream
048     * <li>copy - these methods copy all the data from one stream to another
049     * <li>contentEquals - these methods compare the content of two streams
050     * </ul>
051     * <p>
052     * The byte-to-char methods and char-to-byte methods involve a conversion step.
053     * Two methods are provided in each case, one that uses the platform default
054     * encoding and the other which allows you to specify an encoding. You are
055     * encouraged to always specify an encoding because relying on the platform
056     * default can lead to unexpected results, for example when moving from
057     * development to production.
058     * <p>
059     * All the methods in this class that read a stream are buffered internally.
060     * This means that there is no cause to use a <code>BufferedInputStream</code>
061     * or <code>BufferedReader</code>. The default buffer size of 4K has been shown
062     * to be efficient in tests.
063     * <p>
064     * Wherever possible, the methods in this class do <em>not</em> flush or close
065     * the stream. This is to avoid making non-portable assumptions about the
066     * streams' origin and further use. Thus the caller is still responsible for
067     * closing streams after use.
068     * <p>
069     * Origin of code: Excalibur.
070     *
071     * @author Peter Donald
072     * @author Jeff Turner
073     * @author Matthew Hawthorne
074     * @author Stephen Colebourne
075     * @author Gareth Davis
076     * @author Ian Springer
077     * @author Niall Pemberton
078     * @author Sandy McArthur
079     * @version $Id: IOUtils.java 481854 2006-12-03 18:30:07Z scolebourne $
080     */
081    public class IOUtils {
082        // NOTE: This class is focussed on InputStream, OutputStream, Reader and
083        // Writer. Each method should take at least one of these as a parameter,
084        // or return one of them.
085    
086        /**
087         * The Unix directory separator character.
088         */
089        public static final char DIR_SEPARATOR_UNIX = '/';
090        /**
091         * The Windows directory separator character.
092         */
093        public static final char DIR_SEPARATOR_WINDOWS = '\\';
094        /**
095         * The system directory separator character.
096         */
097        public static final char DIR_SEPARATOR = File.separatorChar;
098        /**
099         * 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);
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         */
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         */
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         */
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         */
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         */
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         */
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         */
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         */
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        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        public static String toString(byte[] input) throws IOException {
414            return new String(input);
415        }
416    
417        /**
418         * Get the contents of a <code>byte[]</code> as a String
419         * using the specified character encoding.
420         * <p>
421         * Character encoding names can be found at
422         * <a href="http://www.iana.org/assignments/character-sets">IANA</a>.
423         * 
424         * @param input the byte array to read from
425         * @param encoding  the encoding to use, null means platform default
426         * @return the requested String
427         * @throws NullPointerException if the input is null
428         * @throws IOException if an I/O error occurs (never occurs)
429         * @deprecated Use {@link String#String(byte[],String)}
430         */
431        public static String toString(byte[] input, String encoding)
432                throws IOException {
433            if (encoding == null) {
434                return new String(input);
435            } else {
436                return new String(input, encoding);
437            }
438        }
439    
440        // readLines
441        //-----------------------------------------------------------------------
442        /**
443         * Get the contents of an <code>InputStream</code> as a list of Strings,
444         * one entry per line, using the default character encoding of the platform.
445         * <p>
446         * This method buffers the input internally, so there is no need to use a
447         * <code>BufferedInputStream</code>.
448         *
449         * @param input  the <code>InputStream</code> to read from, not null
450         * @return the list of Strings, never null
451         * @throws NullPointerException if the input is null
452         * @throws IOException if an I/O error occurs
453         * @since Commons IO 1.1
454         */
455        public static List readLines(InputStream input) throws IOException {
456            InputStreamReader reader = new InputStreamReader(input);
457            return readLines(reader);
458        }
459    
460        /**
461         * Get the contents of an <code>InputStream</code> as a list of Strings,
462         * one entry per line, using the specified character encoding.
463         * <p>
464         * Character encoding names can be found at
465         * <a href="http://www.iana.org/assignments/character-sets">IANA</a>.
466         * <p>
467         * This method buffers the input internally, so there is no need to use a
468         * <code>BufferedInputStream</code>.
469         *
470         * @param input  the <code>InputStream</code> to read from, not null
471         * @param encoding  the encoding to use, null means platform default
472         * @return the list of Strings, never null
473         * @throws NullPointerException if the input is null
474         * @throws IOException if an I/O error occurs
475         * @since Commons IO 1.1
476         */
477        public static List readLines(InputStream input, String encoding) throws IOException {
478            if (encoding == null) {
479                return readLines(input);
480            } else {
481                InputStreamReader reader = new InputStreamReader(input, encoding);
482                return readLines(reader);
483            }
484        }
485    
486        /**
487         * Get the contents of a <code>Reader</code> as a list of Strings,
488         * one entry per line.
489         * <p>
490         * This method buffers the input internally, so there is no need to use a
491         * <code>BufferedReader</code>.
492         *
493         * @param input  the <code>Reader</code> to read from, not null
494         * @return the list of Strings, never null
495         * @throws NullPointerException if the input is null
496         * @throws IOException if an I/O error occurs
497         * @since Commons IO 1.1
498         */
499        public static List readLines(Reader input) throws IOException {
500            BufferedReader reader = new BufferedReader(input);
501            List list = new ArrayList();
502            String line = reader.readLine();
503            while (line != null) {
504                list.add(line);
505                line = reader.readLine();
506            }
507            return list;
508        }
509    
510        // lineIterator
511        //-----------------------------------------------------------------------
512        /**
513         * Return an Iterator for the lines in a <code>Reader</code>.
514         * <p>
515         * <code>LineIterator</code> holds a reference to the open
516         * <code>Reader</code> specified here. When you have finished with the
517         * iterator you should close the reader to free internal resources.
518         * This can be done by closing the reader directly, or by calling
519         * {@link LineIterator#close()} or {@link LineIterator#closeQuietly(LineIterator)}.
520         * <p>
521         * The recommended usage pattern is:
522         * <pre>
523         * try {
524         *   LineIterator it = IOUtils.lineIterator(reader);
525         *   while (it.hasNext()) {
526         *     String line = it.nextLine();
527         *     /// do something with line
528         *   }
529         * } finally {
530         *   IOUtils.closeQuietly(reader);
531         * }
532         * </pre>
533         *
534         * @param reader  the <code>Reader</code> to read from, not null
535         * @return an Iterator of the lines in the reader, never null
536         * @throws IllegalArgumentException if the reader is null
537         * @since Commons IO 1.2
538         */
539        public static LineIterator lineIterator(Reader reader) {
540            return new LineIterator(reader);
541        }
542    
543        /**
544         * Return an Iterator for the lines in an <code>InputStream</code>, using
545         * the character encoding specified (or default encoding if null).
546         * <p>
547         * <code>LineIterator</code> holds a reference to the open
548         * <code>InputStream</code> specified here. When you have finished with
549         * the iterator you should close the stream to free internal resources.
550         * This can be done by closing the stream directly, or by calling
551         * {@link LineIterator#close()} or {@link LineIterator#closeQuietly(LineIterator)}.
552         * <p>
553         * The recommended usage pattern is:
554         * <pre>
555         * try {
556         *   LineIterator it = IOUtils.lineIterator(stream, "UTF-8");
557         *   while (it.hasNext()) {
558         *     String line = it.nextLine();
559         *     /// do something with line
560         *   }
561         * } finally {
562         *   IOUtils.closeQuietly(stream);
563         * }
564         * </pre>
565         *
566         * @param input  the <code>InputStream</code> to read from, not null
567         * @param encoding  the encoding to use, null means platform default
568         * @return an Iterator of the lines in the reader, never null
569         * @throws IllegalArgumentException if the input is null
570         * @throws IOException if an I/O error occurs, such as if the encoding is invalid
571         * @since Commons IO 1.2
572         */
573        public static LineIterator lineIterator(InputStream input, String encoding) 
574                         throws IOException {
575            Reader reader = null;
576            if (encoding == null) {
577                reader = new InputStreamReader(input);
578            } else {
579                reader = new InputStreamReader(input, encoding);
580            }
581            return new LineIterator(reader);
582        }
583    
584        //-----------------------------------------------------------------------
585        /**
586         * Convert the specified string to an input stream, encoded as bytes
587         * using the default character encoding of the platform.
588         *
589         * @param input the string to convert
590         * @return an input stream
591         * @since Commons IO 1.1
592         */
593        public static InputStream toInputStream(String input) {
594            byte[] bytes = input.getBytes();
595            return new ByteArrayInputStream(bytes);
596        }
597    
598        /**
599         * Convert the specified string to an input stream, encoded as bytes
600         * using the specified character encoding.
601         * <p>
602         * Character encoding names can be found at
603         * <a href="http://www.iana.org/assignments/character-sets">IANA</a>.
604         *
605         * @param input the string to convert
606         * @param encoding the encoding to use, null means platform default
607         * @throws IOException if the encoding is invalid
608         * @return an input stream
609         * @since Commons IO 1.1
610         */
611        public static InputStream toInputStream(String input, String encoding) throws IOException {
612            byte[] bytes = encoding != null ? input.getBytes(encoding) : input.getBytes();
613            return new ByteArrayInputStream(bytes);
614        }
615    
616        // write byte[]
617        //-----------------------------------------------------------------------
618        /**
619         * Writes bytes from a <code>byte[]</code> to an <code>OutputStream</code>.
620         * 
621         * @param data  the byte array to write, do not modify during output,
622         * null ignored
623         * @param output  the <code>OutputStream</code> to write to
624         * @throws NullPointerException if output is null
625         * @throws IOException if an I/O error occurs
626         * @since Commons IO 1.1
627         */
628        public static void write(byte[] data, OutputStream output)
629                throws IOException {
630            if (data != null) {
631                output.write(data);
632            }
633        }
634    
635        /**
636         * Writes bytes from a <code>byte[]</code> to chars on a <code>Writer</code>
637         * using the default character encoding of the platform.
638         * <p>
639         * This method uses {@link String#String(byte[])}.
640         * 
641         * @param data  the byte array to write, do not modify during output,
642         * null ignored
643         * @param output  the <code>Writer</code> to write to
644         * @throws NullPointerException if output is null
645         * @throws IOException if an I/O error occurs
646         * @since Commons IO 1.1
647         */
648        public static void write(byte[] data, Writer output) throws IOException {
649            if (data != null) {
650                output.write(new String(data));
651            }
652        }
653    
654        /**
655         * Writes bytes from a <code>byte[]</code> to chars on a <code>Writer</code>
656         * using the specified character encoding.
657         * <p>
658         * Character encoding names can be found at
659         * <a href="http://www.iana.org/assignments/character-sets">IANA</a>.
660         * <p>
661         * This method uses {@link String#String(byte[], String)}.
662         * 
663         * @param data  the byte array to write, do not modify during output,
664         * null ignored
665         * @param output  the <code>Writer</code> to write to
666         * @param encoding  the encoding to use, null means platform default
667         * @throws NullPointerException if output is null
668         * @throws IOException if an I/O error occurs
669         * @since Commons IO 1.1
670         */
671        public static void write(byte[] data, Writer output, String encoding)
672                throws IOException {
673            if (data != null) {
674                if (encoding == null) {
675                    write(data, output);
676                } else {
677                    output.write(new String(data, encoding));
678                }
679            }
680        }
681    
682        // write char[]
683        //-----------------------------------------------------------------------
684        /**
685         * Writes chars from a <code>char[]</code> to a <code>Writer</code>
686         * using the default character encoding of the platform.
687         * 
688         * @param data  the char array to write, do not modify during output,
689         * null ignored
690         * @param output  the <code>Writer</code> to write to
691         * @throws NullPointerException if output is null
692         * @throws IOException if an I/O error occurs
693         * @since Commons IO 1.1
694         */
695        public static void write(char[] data, Writer output) throws IOException {
696            if (data != null) {
697                output.write(data);
698            }
699        }
700    
701        /**
702         * Writes chars from a <code>char[]</code> to bytes on an
703         * <code>OutputStream</code>.
704         * <p>
705         * This method uses {@link String#String(char[])} and
706         * {@link String#getBytes()}.
707         * 
708         * @param data  the char array to write, do not modify during output,
709         * null ignored
710         * @param output  the <code>OutputStream</code> to write to
711         * @throws NullPointerException if output is null
712         * @throws IOException if an I/O error occurs
713         * @since Commons IO 1.1
714         */
715        public static void write(char[] data, OutputStream output)
716                throws IOException {
717            if (data != null) {
718                output.write(new String(data).getBytes());
719            }
720        }
721    
722        /**
723         * Writes chars from a <code>char[]</code> to bytes on an
724         * <code>OutputStream</code> using the specified character encoding.
725         * <p>
726         * Character encoding names can be found at
727         * <a href="http://www.iana.org/assignments/character-sets">IANA</a>.
728         * <p>
729         * This method uses {@link String#String(char[])} and
730         * {@link String#getBytes(String)}.
731         * 
732         * @param data  the char array to write, do not modify during output,
733         * null ignored
734         * @param output  the <code>OutputStream</code> to write to
735         * @param encoding  the encoding to use, null means platform default
736         * @throws NullPointerException if output is null
737         * @throws IOException if an I/O error occurs
738         * @since Commons IO 1.1
739         */
740        public static void write(char[] data, OutputStream output, String encoding)
741                throws IOException {
742            if (data != null) {
743                if (encoding == null) {
744                    write(data, output);
745                } else {
746                    output.write(new String(data).getBytes(encoding));
747                }
748            }
749        }
750    
751        // write String
752        //-----------------------------------------------------------------------
753        /**
754         * Writes chars from a <code>String</code> to a <code>Writer</code>.
755         * 
756         * @param data  the <code>String</code> to write, null ignored
757         * @param output  the <code>Writer</code> to write to
758         * @throws NullPointerException if output is null
759         * @throws IOException if an I/O error occurs
760         * @since Commons IO 1.1
761         */
762        public static void write(String data, Writer output) throws IOException {
763            if (data != null) {
764                output.write(data);
765            }
766        }
767    
768        /**
769         * Writes chars from a <code>String</code> to bytes on an
770         * <code>OutputStream</code> using the default character encoding of the
771         * platform.
772         * <p>
773         * This method uses {@link String#getBytes()}.
774         * 
775         * @param data  the <code>String</code> to write, null ignored
776         * @param output  the <code>OutputStream</code> to write to
777         * @throws NullPointerException if output is null
778         * @throws IOException if an I/O error occurs
779         * @since Commons IO 1.1
780         */
781        public static void write(String data, OutputStream output)
782                throws IOException {
783            if (data != null) {
784                output.write(data.getBytes());
785            }
786        }
787    
788        /**
789         * Writes chars from a <code>String</code> to bytes on an
790         * <code>OutputStream</code> using the specified character encoding.
791         * <p>
792         * Character encoding names can be found at
793         * <a href="http://www.iana.org/assignments/character-sets">IANA</a>.
794         * <p>
795         * This method uses {@link String#getBytes(String)}.
796         * 
797         * @param data  the <code>String</code> to write, null ignored
798         * @param output  the <code>OutputStream</code> to write to
799         * @param encoding  the encoding to use, null means platform default
800         * @throws NullPointerException if output is null
801         * @throws IOException if an I/O error occurs
802         * @since Commons IO 1.1
803         */
804        public static void write(String data, OutputStream output, String encoding)
805                throws IOException {
806            if (data != null) {
807                if (encoding == null) {
808                    write(data, output);
809                } else {
810                    output.write(data.getBytes(encoding));
811                }
812            }
813        }
814    
815        // write StringBuffer
816        //-----------------------------------------------------------------------
817        /**
818         * Writes chars from a <code>StringBuffer</code> to a <code>Writer</code>.
819         * 
820         * @param data  the <code>StringBuffer</code> to write, null ignored
821         * @param output  the <code>Writer</code> to write to
822         * @throws NullPointerException if output is null
823         * @throws IOException if an I/O error occurs
824         * @since Commons IO 1.1
825         */
826        public static void write(StringBuffer data, Writer output)
827                throws IOException {
828            if (data != null) {
829                output.write(data.toString());
830            }
831        }
832    
833        /**
834         * Writes chars from a <code>StringBuffer</code> to bytes on an
835         * <code>OutputStream</code> using the default character encoding of the
836         * platform.
837         * <p>
838         * This method uses {@link String#getBytes()}.
839         * 
840         * @param data  the <code>StringBuffer</code> to write, null ignored
841         * @param output  the <code>OutputStream</code> to write to
842         * @throws NullPointerException if output is null
843         * @throws IOException if an I/O error occurs
844         * @since Commons IO 1.1
845         */
846        public static void write(StringBuffer data, OutputStream output)
847                throws IOException {
848            if (data != null) {
849                output.write(data.toString().getBytes());
850            }
851        }
852    
853        /**
854         * Writes chars from a <code>StringBuffer</code> to bytes on an
855         * <code>OutputStream</code> using the specified character encoding.
856         * <p>
857         * Character encoding names can be found at
858         * <a href="http://www.iana.org/assignments/character-sets">IANA</a>.
859         * <p>
860         * This method uses {@link String#getBytes(String)}.
861         * 
862         * @param data  the <code>StringBuffer</code> to write, null ignored
863         * @param output  the <code>OutputStream</code> to write to
864         * @param encoding  the encoding to use, null means platform default
865         * @throws NullPointerException if output is null
866         * @throws IOException if an I/O error occurs
867         * @since Commons IO 1.1
868         */
869        public static void write(StringBuffer data, OutputStream output,
870                String encoding) throws IOException {
871            if (data != null) {
872                if (encoding == null) {
873                    write(data, output);
874                } else {
875                    output.write(data.toString().getBytes(encoding));
876                }
877            }
878        }
879    
880        // writeLines
881        //-----------------------------------------------------------------------
882        /**
883         * Writes the <code>toString()</code> value of each item in a collection to
884         * an <code>OutputStream</code> line by line, using the default character
885         * encoding of the platform and the specified line ending.
886         *
887         * @param lines  the lines to write, null entries produce blank lines
888         * @param lineEnding  the line separator to use, null is system default
889         * @param output  the <code>OutputStream</code> to write to, not null, not closed
890         * @throws NullPointerException if the output is null
891         * @throws IOException if an I/O error occurs
892         * @since Commons IO 1.1
893         */
894        public static void writeLines(Collection lines, String lineEnding,
895                OutputStream output) throws IOException {
896            if (lines == null) {
897                return;
898            }
899            if (lineEnding == null) {
900                lineEnding = LINE_SEPARATOR;
901            }
902            for (Iterator it = lines.iterator(); it.hasNext(); ) {
903                Object line = it.next();
904                if (line != null) {
905                    output.write(line.toString().getBytes());
906                }
907                output.write(lineEnding.getBytes());
908            }
909        }
910    
911        /**
912         * Writes the <code>toString()</code> value of each item in a collection to
913         * an <code>OutputStream</code> line by line, using the specified character
914         * encoding and the specified line ending.
915         * <p>
916         * Character encoding names can be found at
917         * <a href="http://www.iana.org/assignments/character-sets">IANA</a>.
918         *
919         * @param lines  the lines to write, null entries produce blank lines
920         * @param lineEnding  the line separator to use, null is system default
921         * @param output  the <code>OutputStream</code> to write to, not null, not closed
922         * @param encoding  the encoding to use, null means platform default
923         * @throws NullPointerException if the output is null
924         * @throws IOException if an I/O error occurs
925         * @since Commons IO 1.1
926         */
927        public static void writeLines(Collection lines, String lineEnding,
928                OutputStream output, String encoding) throws IOException {
929            if (encoding == null) {
930                writeLines(lines, lineEnding, output);
931            } else {
932                if (lines == null) {
933                    return;
934                }
935                if (lineEnding == null) {
936                    lineEnding = LINE_SEPARATOR;
937                }
938                for (Iterator it = lines.iterator(); it.hasNext(); ) {
939                    Object line = it.next();
940                    if (line != null) {
941                        output.write(line.toString().getBytes(encoding));
942                    }
943                    output.write(lineEnding.getBytes(encoding));
944                }
945            }
946        }
947    
948        /**
949         * Writes the <code>toString()</code> value of each item in a collection to
950         * a <code>Writer</code> line by line, using the specified line ending.
951         *
952         * @param lines  the lines to write, null entries produce blank lines
953         * @param lineEnding  the line separator to use, null is system default
954         * @param writer  the <code>Writer</code> to write to, not null, not closed
955         * @throws NullPointerException if the input is null
956         * @throws IOException if an I/O error occurs
957         * @since Commons IO 1.1
958         */
959        public static void writeLines(Collection lines, String lineEnding,
960                Writer writer) throws IOException {
961            if (lines == null) {
962                return;
963            }
964            if (lineEnding == null) {
965                lineEnding = LINE_SEPARATOR;
966            }
967            for (Iterator it = lines.iterator(); it.hasNext(); ) {
968                Object line = it.next();
969                if (line != null) {
970                    writer.write(line.toString());
971                }
972                writer.write(lineEnding);
973            }
974        }
975    
976        // copy from InputStream
977        //-----------------------------------------------------------------------
978        /**
979         * Copy bytes from an <code>InputStream</code> to an
980         * <code>OutputStream</code>.
981         * <p>
982         * This method buffers the input internally, so there is no need to use a
983         * <code>BufferedInputStream</code>.
984         * <p>
985         * Large streams (over 2GB) will return a bytes copied value of
986         * <code>-1</code> after the copy has completed since the correct
987         * number of bytes cannot be returned as an int. For large streams
988         * use the <code>copyLarge(InputStream, OutputStream)</code> method.
989         * 
990         * @param input  the <code>InputStream</code> to read from
991         * @param output  the <code>OutputStream</code> to write to
992         * @return the number of bytes copied
993         * @throws NullPointerException if the input or output is null
994         * @throws IOException if an I/O error occurs
995         * @throws ArithmeticException if the byte count is too large
996         * @since Commons IO 1.1
997         */
998        public static int copy(InputStream input, OutputStream output) throws IOException {
999            long count = copyLarge(input, output);
1000            if (count > Integer.MAX_VALUE) {
1001                return -1;
1002            }
1003            return (int) count;
1004        }
1005    
1006        /**
1007         * Copy bytes from a large (over 2GB) <code>InputStream</code> to an
1008         * <code>OutputStream</code>.
1009         * <p>
1010         * This method buffers the input internally, so there is no need to use a
1011         * <code>BufferedInputStream</code>.
1012         * 
1013         * @param input  the <code>InputStream</code> to read from
1014         * @param output  the <code>OutputStream</code> to write to
1015         * @return the number of bytes copied
1016         * @throws NullPointerException if the input or output is null
1017         * @throws IOException if an I/O error occurs
1018         * @since Commons IO 1.3
1019         */
1020        public static long copyLarge(InputStream input, OutputStream output)
1021                throws IOException {
1022            byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
1023            long count = 0;
1024            int n = 0;
1025            while (-1 != (n = input.read(buffer))) {
1026                output.write(buffer, 0, n);
1027                count += n;
1028            }
1029            return count;
1030        }
1031    
1032        /**
1033         * Copy bytes from an <code>InputStream</code> to chars on a
1034         * <code>Writer</code> using the default character encoding of the platform.
1035         * <p>
1036         * This method buffers the input internally, so there is no need to use a
1037         * <code>BufferedInputStream</code>.
1038         * <p>
1039         * This method uses {@link InputStreamReader}.
1040         *
1041         * @param input  the <code>InputStream</code> to read from
1042         * @param output  the <code>Writer</code> to write to
1043         * @throws NullPointerException if the input or output is null
1044         * @throws IOException if an I/O error occurs
1045         * @since Commons IO 1.1
1046         */
1047        public static void copy(InputStream input, Writer output)
1048                throws IOException {
1049            InputStreamReader in = new InputStreamReader(input);
1050            copy(in, output);
1051        }
1052    
1053        /**
1054         * Copy bytes from an <code>InputStream</code> to chars on a
1055         * <code>Writer</code> using the specified character encoding.
1056         * <p>
1057         * This method buffers the input internally, so there is no need to use a
1058         * <code>BufferedInputStream</code>.
1059         * <p>
1060         * Character encoding names can be found at
1061         * <a href="http://www.iana.org/assignments/character-sets">IANA</a>.
1062         * <p>
1063         * This method uses {@link InputStreamReader}.
1064         *
1065         * @param input  the <code>InputStream</code> to read from
1066         * @param output  the <code>Writer</code> to write to
1067         * @param encoding  the encoding to use, null means platform default
1068         * @throws NullPointerException if the input or output is null
1069         * @throws IOException if an I/O error occurs
1070         * @since Commons IO 1.1
1071         */
1072        public static void copy(InputStream input, Writer output, String encoding)
1073                throws IOException {
1074            if (encoding == null) {
1075                copy(input, output);
1076            } else {
1077                InputStreamReader in = new InputStreamReader(input, encoding);
1078                copy(in, output);
1079            }
1080        }
1081    
1082        // copy from Reader
1083        //-----------------------------------------------------------------------
1084        /**
1085         * Copy chars from a <code>Reader</code> to a <code>Writer</code>.
1086         * <p>
1087         * This method buffers the input internally, so there is no need to use a
1088         * <code>BufferedReader</code>.
1089         * <p>
1090         * Large streams (over 2GB) will return a chars copied value of
1091         * <code>-1</code> after the copy has completed since the correct
1092         * number of chars cannot be returned as an int. For large streams
1093         * use the <code>copyLarge(Reader, Writer)</code> method.
1094         *
1095         * @param input  the <code>Reader</code> to read from
1096         * @param output  the <code>Writer</code> to write to
1097         * @return the number of characters copied
1098         * @throws NullPointerException if the input or output is null
1099         * @throws IOException if an I/O error occurs
1100         * @throws ArithmeticException if the character count is too large
1101         * @since Commons IO 1.1
1102         */
1103        public static int copy(Reader input, Writer output) throws IOException {
1104            long count = copyLarge(input, output);
1105            if (count > Integer.MAX_VALUE) {
1106                return -1;
1107            }
1108            return (int) count;
1109        }
1110    
1111        /**
1112         * Copy chars from a large (over 2GB) <code>Reader</code> to a <code>Writer</code>.
1113         * <p>
1114         * This method buffers the input internally, so there is no need to use a
1115         * <code>BufferedReader</code>.
1116         *
1117         * @param input  the <code>Reader</code> to read from
1118         * @param output  the <code>Writer</code> to write to
1119         * @return the number of characters copied
1120         * @throws NullPointerException if the input or output is null
1121         * @throws IOException if an I/O error occurs
1122         * @since Commons IO 1.3
1123         */
1124        public static long copyLarge(Reader input, Writer output) throws IOException {
1125            char[] buffer = new char[DEFAULT_BUFFER_SIZE];
1126            long count = 0;
1127            int n = 0;
1128            while (-1 != (n = input.read(buffer))) {
1129                output.write(buffer, 0, n);
1130                count += n;
1131            }
1132            return count;
1133        }
1134    
1135        /**
1136         * Copy chars from a <code>Reader</code> to bytes on an
1137         * <code>OutputStream</code> using the default character encoding of the
1138         * platform, and calling flush.
1139         * <p>
1140         * This method buffers the input internally, so there is no need to use a
1141         * <code>BufferedReader</code>.
1142         * <p>
1143         * Due to the implementation of OutputStreamWriter, this method performs a
1144         * flush.
1145         * <p>
1146         * This method uses {@link OutputStreamWriter}.
1147         *
1148         * @param input  the <code>Reader</code> to read from
1149         * @param output  the <code>OutputStream</code> to write to
1150         * @throws NullPointerException if the input or output is null
1151         * @throws IOException if an I/O error occurs
1152         * @since Commons IO 1.1
1153         */
1154        public static void copy(Reader input, OutputStream output)
1155                throws IOException {
1156            OutputStreamWriter out = new OutputStreamWriter(output);
1157            copy(input, out);
1158            // XXX Unless anyone is planning on rewriting OutputStreamWriter, we
1159            // have to flush here.
1160            out.flush();
1161        }
1162    
1163        /**
1164         * Copy chars from a <code>Reader</code> to bytes on an
1165         * <code>OutputStream</code> using the specified character encoding, and
1166         * calling flush.
1167         * <p>
1168         * This method buffers the input internally, so there is no need to use a
1169         * <code>BufferedReader</code>.
1170         * <p>
1171         * Character encoding names can be found at
1172         * <a href="http://www.iana.org/assignments/character-sets">IANA</a>.
1173         * <p>
1174         * Due to the implementation of OutputStreamWriter, this method performs a
1175         * flush.
1176         * <p>
1177         * This method uses {@link OutputStreamWriter}.
1178         *
1179         * @param input  the <code>Reader</code> to read from
1180         * @param output  the <code>OutputStream</code> to write to
1181         * @param encoding  the encoding to use, null means platform default
1182         * @throws NullPointerException if the input or output is null
1183         * @throws IOException if an I/O error occurs
1184         * @since Commons IO 1.1
1185         */
1186        public static void copy(Reader input, OutputStream output, String encoding)
1187                throws IOException {
1188            if (encoding == null) {
1189                copy(input, output);
1190            } else {
1191                OutputStreamWriter out = new OutputStreamWriter(output, encoding);
1192                copy(input, out);
1193                // XXX Unless anyone is planning on rewriting OutputStreamWriter,
1194                // we have to flush here.
1195                out.flush();
1196            }
1197        }
1198    
1199        // content equals
1200        //-----------------------------------------------------------------------
1201        /**
1202         * Compare the contents of two Streams to determine if they are equal or
1203         * not.
1204         * <p>
1205         * This method buffers the input internally using
1206         * <code>BufferedInputStream</code> if they are not already buffered.
1207         *
1208         * @param input1  the first stream
1209         * @param input2  the second stream
1210         * @return true if the content of the streams are equal or they both don't
1211         * exist, false otherwise
1212         * @throws NullPointerException if either input is null
1213         * @throws IOException if an I/O error occurs
1214         */
1215        public static boolean contentEquals(InputStream input1, InputStream input2)
1216                throws IOException {
1217            if (!(input1 instanceof BufferedInputStream)) {
1218                input1 = new BufferedInputStream(input1);
1219            }
1220            if (!(input2 instanceof BufferedInputStream)) {
1221                input2 = new BufferedInputStream(input2);
1222            }
1223    
1224            int ch = input1.read();
1225            while (-1 != ch) {
1226                int ch2 = input2.read();
1227                if (ch != ch2) {
1228                    return false;
1229                }
1230                ch = input1.read();
1231            }
1232    
1233            int ch2 = input2.read();
1234            return (ch2 == -1);
1235        }
1236    
1237        /**
1238         * Compare the contents of two Readers to determine if they are equal or
1239         * not.
1240         * <p>
1241         * This method buffers the input internally using
1242         * <code>BufferedReader</code> if they are not already buffered.
1243         *
1244         * @param input1  the first reader
1245         * @param input2  the second reader
1246         * @return true if the content of the readers are equal or they both don't
1247         * exist, false otherwise
1248         * @throws NullPointerException if either input is null
1249         * @throws IOException if an I/O error occurs
1250         * @since Commons IO 1.1
1251         */
1252        public static boolean contentEquals(Reader input1, Reader input2)
1253                throws IOException {
1254            if (!(input1 instanceof BufferedReader)) {
1255                input1 = new BufferedReader(input1);
1256            }
1257            if (!(input2 instanceof BufferedReader)) {
1258                input2 = new BufferedReader(input2);
1259            }
1260    
1261            int ch = input1.read();
1262            while (-1 != ch) {
1263                int ch2 = input2.read();
1264                if (ch != ch2) {
1265                    return false;
1266                }
1267                ch = input1.read();
1268            }
1269    
1270            int ch2 = input2.read();
1271            return (ch2 == -1);
1272        }
1273    
1274    }