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.Closeable;
024    import java.io.EOFException;
025    import java.io.File;
026    import java.io.IOException;
027    import java.io.InputStream;
028    import java.io.InputStreamReader;
029    import java.io.OutputStream;
030    import java.io.OutputStreamWriter;
031    import java.io.PrintWriter;
032    import java.io.Reader;
033    import java.io.Writer;
034    import java.net.Socket;
035    import java.net.URI;
036    import java.net.URL;
037    import java.util.ArrayList;
038    import java.util.Collection;
039    import java.util.List;
040    
041    import org.apache.commons.io.output.ByteArrayOutputStream;
042    import org.apache.commons.io.output.StringBuilderWriter;
043    
044    /**
045     * General IO stream manipulation utilities.
046     * <p>
047     * This class provides static utility methods for input/output operations.
048     * <ul>
049     * <li>closeQuietly - these methods close a stream ignoring nulls and exceptions
050     * <li>toXxx/read - these methods read data from a stream
051     * <li>write - these methods write data to a stream
052     * <li>copy - these methods copy all the data from one stream to another
053     * <li>contentEquals - these methods compare the content of two streams
054     * </ul>
055     * <p>
056     * The byte-to-char methods and char-to-byte methods involve a conversion step.
057     * Two methods are provided in each case, one that uses the platform default
058     * encoding and the other which allows you to specify an encoding. You are
059     * encouraged to always specify an encoding because relying on the platform
060     * default can lead to unexpected results, for example when moving from
061     * development to production.
062     * <p>
063     * All the methods in this class that read a stream are buffered internally.
064     * This means that there is no cause to use a <code>BufferedInputStream</code>
065     * or <code>BufferedReader</code>. The default buffer size of 4K has been shown
066     * to be efficient in tests.
067     * <p>
068     * Wherever possible, the methods in this class do <em>not</em> flush or close
069     * the stream. This is to avoid making non-portable assumptions about the
070     * streams' origin and further use. Thus the caller is still responsible for
071     * closing streams after use.
072     * <p>
073     * Origin of code: Excalibur.
074     *
075     * @author Peter Donald
076     * @author Jeff Turner
077     * @author Matthew Hawthorne
078     * @author Stephen Colebourne
079     * @author Gareth Davis
080     * @author Ian Springer
081     * @author Sandy McArthur
082     * @version $Id: IOUtils.java 1091653 2011-04-13 05:22:45Z ggregory $
083     */
084    public class IOUtils {
085        // NOTE: This class is focussed on InputStream, OutputStream, Reader and
086        // Writer. Each method should take at least one of these as a parameter,
087        // or return one of them.
088    
089        /**
090         * The Unix directory separator character.
091         */
092        public static final char DIR_SEPARATOR_UNIX = '/';
093        /**
094         * The Windows directory separator character.
095         */
096        public static final char DIR_SEPARATOR_WINDOWS = '\\';
097        /**
098         * The system directory separator character.
099         */
100        public static final char DIR_SEPARATOR = File.separatorChar;
101        /**
102         * The Unix line separator string.
103         */
104        public static final String LINE_SEPARATOR_UNIX = "\n";
105        /**
106         * The Windows line separator string.
107         */
108        public static final String LINE_SEPARATOR_WINDOWS = "\r\n";
109        /**
110         * The system line separator string.
111         */
112        public static final String LINE_SEPARATOR;
113        static {
114            // avoid security issues
115            StringBuilderWriter buf = new StringBuilderWriter(4);
116            PrintWriter out = new PrintWriter(buf);
117            out.println();
118            LINE_SEPARATOR = buf.toString();
119            out.close();
120        }
121    
122        /**
123         * The default buffer size to use for 
124         * {@link #copyLarge(InputStream, OutputStream)}
125         * and
126         * {@link #copyLarge(Reader, Writer)}
127         */
128        private static final int DEFAULT_BUFFER_SIZE = 1024 * 4;
129    
130        /**
131         * The default buffer size to use for the skip() methods.
132         */
133        private static final int SKIP_BUFFER_SIZE = 2048;
134        
135        // Allocated in the skip method if necessary.
136        private static char[] SKIP_CHAR_BUFFER;
137        private static byte[] SKIP_BYTE_BUFFER;
138    
139        /**
140         * Instances should NOT be constructed in standard programming.
141         */
142        public IOUtils() {
143            super();
144        }
145    
146        //-----------------------------------------------------------------------
147        /**
148         * Unconditionally close an <code>Reader</code>.
149         * <p>
150         * Equivalent to {@link Reader#close()}, except any exceptions will be ignored.
151         * This is typically used in finally blocks.
152         * <p>
153         * Example code:
154         * <pre>
155         *   char[] data = new char[1024];
156         *   Reader in = null;
157         *   try {
158         *       in = new FileReader("foo.txt");
159         *       in.read(data);
160         *       in.close(); //close errors are handled
161         *   } catch (Exception e) {
162         *       // error handling
163         *   } finally {
164         *       IOUtils.closeQuietly(in);
165         *   }
166         * </pre>
167         * 
168         * @param input  the Reader to close, may be null or already closed
169         */
170        public static void closeQuietly(Reader input) {
171            closeQuietly((Closeable)input);
172        }
173    
174        /**
175         * Unconditionally close a <code>Writer</code>.
176         * <p>
177         * Equivalent to {@link Writer#close()}, except any exceptions will be ignored.
178         * This is typically used in finally blocks.
179         * <p>
180         * Example code:
181         * <pre>
182         *   Writer out = null;
183         *   try {
184         *       out = new StringWriter();
185         *       out.write("Hello World");
186         *       out.close(); //close errors are handled
187         *   } catch (Exception e) {
188         *       // error handling
189         *   } finally {
190         *       IOUtils.closeQuietly(out);
191         *   }
192         * </pre>
193         *
194         * @param output  the Writer to close, may be null or already closed
195         */
196        public static void closeQuietly(Writer output) {
197            closeQuietly((Closeable)output);
198        }
199    
200        /**
201         * Unconditionally close an <code>InputStream</code>.
202         * <p>
203         * Equivalent to {@link InputStream#close()}, except any exceptions will be ignored.
204         * This is typically used in finally blocks.
205         * <p>
206         * Example code:
207         * <pre>
208         *   byte[] data = new byte[1024];
209         *   InputStream in = null;
210         *   try {
211         *       in = new FileInputStream("foo.txt");
212         *       in.read(data);
213         *       in.close(); //close errors are handled
214         *   } catch (Exception e) {
215         *       // error handling
216         *   } finally {
217         *       IOUtils.closeQuietly(in);
218         *   }
219         * </pre>
220         *
221         * @param input  the InputStream to close, may be null or already closed
222         */
223        public static void closeQuietly(InputStream input) {
224            closeQuietly((Closeable)input);
225        }
226    
227        /**
228         * Unconditionally close an <code>OutputStream</code>.
229         * <p>
230         * Equivalent to {@link OutputStream#close()}, except any exceptions will be ignored.
231         * This is typically used in finally blocks.
232         * <p>
233         * Example code:
234         * <pre>
235         * byte[] data = "Hello, World".getBytes();
236         *
237         * OutputStream out = null;
238         * try {
239         *     out = new FileOutputStream("foo.txt");
240         *     out.write(data);
241         *     out.close(); //close errors are handled
242         * } catch (IOException e) {
243         *     // error handling
244         * } finally {
245         *     IOUtils.closeQuietly(out);
246         * }
247         * </pre>
248         *
249         * @param output  the OutputStream to close, may be null or already closed
250         */
251        public static void closeQuietly(OutputStream output) {
252            closeQuietly((Closeable)output);
253        }
254        
255        /**
256         * Unconditionally close a <code>Closeable</code>.
257         * <p>
258         * Equivalent to {@link Closeable#close()}, except any exceptions will be ignored.
259         * This is typically used in finally blocks.
260         * <p>
261         * Example code:
262         * <pre>
263         *   Closeable closeable = null;
264         *   try {
265         *       closeable = new FileReader("foo.txt");
266         *       // process closeable
267         *       closeable.close();
268         *   } catch (Exception e) {
269         *       // error handling
270         *   } finally {
271         *       IOUtils.closeQuietly(closeable);
272         *   }
273         * </pre>
274         *
275         * @param closeable the object to close, may be null or already closed
276         * @since Commons IO 2.0
277         */
278        public static void closeQuietly(Closeable closeable) {
279            try {
280                if (closeable != null) {
281                    closeable.close();
282                }
283            } catch (IOException ioe) {
284                // ignore
285            }
286        }
287    
288        /**
289         * Unconditionally close a <code>Socket</code>.
290         * <p>
291         * Equivalent to {@link Socket#close()}, except any exceptions will be ignored.
292         * This is typically used in finally blocks.
293         * <p>
294         * Example code:
295         * <pre>
296         *   Socket socket = null;
297         *   try {
298         *       socket = new Socket("http://www.foo.com/", 80);
299         *       // process socket
300         *       socket.close();
301         *   } catch (Exception e) {
302         *       // error handling
303         *   } finally {
304         *       IOUtils.closeQuietly(socket);
305         *   }
306         * </pre>
307         *
308         * @param sock the Socket to close, may be null or already closed
309         * @since Commons IO 2.0
310         */
311        public static void closeQuietly(Socket sock){
312            if (sock != null){
313                try {
314                    sock.close();
315                } catch (IOException ioe) {
316                    // ignored
317                }
318            }
319        }
320    
321        /**
322         * Fetches entire contents of an <code>InputStream</code> and represent
323         * same data as result InputStream.
324         * <p>
325         * This method is useful where,
326         * <ul>
327         * <li>Source InputStream is slow.</li>
328         * <li>It has network resources associated, so we cannot keep it open for
329         * long time.</li>
330         * <li>It has network timeout associated.</li>
331         * </ul>
332         * It can be used in favor of {@link #toByteArray(InputStream)}, since it
333         * avoids unnecessary allocation and copy of byte[].<br>
334         * This method buffers the input internally, so there is no need to use a
335         * <code>BufferedInputStream</code>.
336         * 
337         * @param input Stream to be fully buffered.
338         * @return A fully buffered stream.
339         * @throws IOException if an I/O error occurs
340         * @since Commons IO 2.0
341         */
342        public static InputStream toBufferedInputStream(InputStream input) throws IOException {
343            return ByteArrayOutputStream.toBufferedInputStream(input);
344        }
345    
346        // read toByteArray
347        //-----------------------------------------------------------------------
348        /**
349         * Get the contents of an <code>InputStream</code> as a <code>byte[]</code>.
350         * <p>
351         * This method buffers the input internally, so there is no need to use a
352         * <code>BufferedInputStream</code>.
353         * 
354         * @param input  the <code>InputStream</code> to read from
355         * @return the requested byte array
356         * @throws NullPointerException if the input is null
357         * @throws IOException if an I/O error occurs
358         */
359        public static byte[] toByteArray(InputStream input) throws IOException {
360            ByteArrayOutputStream output = new ByteArrayOutputStream();
361            copy(input, output);
362            return output.toByteArray();
363        }
364    
365        /**
366         * Get contents of an <code>InputStream</code> as a <code>byte[]</code>.
367         * Use this method instead of <code>toByteArray(InputStream)</code>
368         * when <code>InputStream</code> size is known.
369         * <b>NOTE:</b> the method checks that the length can safely be cast to an int without truncation
370         * before using {@link IOUtils#toByteArray(java.io.InputStream, int)} to read into the byte array.
371         * (Arrays can have no more than Integer.MAX_VALUE entries anyway)
372         * 
373         * @param input the <code>InputStream</code> to read from
374         * @param size the size of <code>InputStream</code>
375         * @return the requested byte array
376         * @throws IOException if an I/O error occurs or <code>InputStream</code> size differ from parameter size
377         * @throws IllegalArgumentException if size is less than zero or size is greater than Integer.MAX_VALUE
378         * @see IOUtils#toByteArray(java.io.InputStream, int)
379         * @since Commons IO 2.1
380         */
381        public static byte[] toByteArray(InputStream input, long size) throws IOException {
382    
383          if(size > Integer.MAX_VALUE) {
384              throw new IllegalArgumentException("Size cannot be greater than Integer max value: " + size);
385          }
386    
387          return toByteArray(input, (int) size);
388        }
389    
390        /** 
391         * Get the contents of an <code>InputStream</code> as a <code>byte[]</code>.
392         * Use this method instead of <code>toByteArray(InputStream)</code>
393         * when <code>InputStream</code> size is known
394         * @param input the <code>InputStream</code> to read from
395         * @param size the size of <code>InputStream</code>
396         * @return the requested byte array
397         * @throws IOException if an I/O error occurs or <code>InputStream</code> size differ from parameter size
398         * @throws IllegalArgumentException if size is less than zero
399         * @since Commons IO 2.1
400         */
401        public static byte[] toByteArray(InputStream input, int size) throws IOException {
402    
403            if(size < 0) {
404                throw new IllegalArgumentException("Size must be equal or greater than zero: " + size);
405            }
406            
407            if(size == 0) {
408                return new byte[0];
409            }
410    
411            byte[] data = new byte[size];
412            int offset = 0;
413            int readed;
414    
415            while(offset < size && (readed = input.read(data, offset, (size - offset))) != -1) {
416                offset += readed;
417            }
418    
419            if(offset != size) {
420                throw new IOException("Unexpected readed size. current: " + offset + ", excepted: " + size);
421            }
422    
423            return data;
424        }
425    
426        /**
427         * Get the contents of a <code>Reader</code> as a <code>byte[]</code>
428         * using the default character encoding of the platform.
429         * <p>
430         * This method buffers the input internally, so there is no need to use a
431         * <code>BufferedReader</code>.
432         * 
433         * @param input  the <code>Reader</code> to read from
434         * @return the requested byte array
435         * @throws NullPointerException if the input is null
436         * @throws IOException if an I/O error occurs
437         */
438        public static byte[] toByteArray(Reader input) throws IOException {
439            ByteArrayOutputStream output = new ByteArrayOutputStream();
440            copy(input, output);
441            return output.toByteArray();
442        }
443    
444        /**
445         * Get the contents of a <code>Reader</code> as a <code>byte[]</code>
446         * using the specified character encoding.
447         * <p>
448         * Character encoding names can be found at
449         * <a href="http://www.iana.org/assignments/character-sets">IANA</a>.
450         * <p>
451         * This method buffers the input internally, so there is no need to use a
452         * <code>BufferedReader</code>.
453         * 
454         * @param input  the <code>Reader</code> to read from
455         * @param encoding  the encoding to use, null means platform default
456         * @return the requested byte array
457         * @throws NullPointerException if the input is null
458         * @throws IOException if an I/O error occurs
459         * @since Commons IO 1.1
460         */
461        public static byte[] toByteArray(Reader input, String encoding)
462                throws IOException {
463            ByteArrayOutputStream output = new ByteArrayOutputStream();
464            copy(input, output, encoding);
465            return output.toByteArray();
466        }
467    
468        /**
469         * Get the contents of a <code>String</code> as a <code>byte[]</code>
470         * using the default character encoding of the platform.
471         * <p>
472         * This is the same as {@link String#getBytes()}.
473         * 
474         * @param input  the <code>String</code> to convert
475         * @return the requested byte array
476         * @throws NullPointerException if the input is null
477         * @throws IOException if an I/O error occurs (never occurs)
478         * @deprecated Use {@link String#getBytes()}
479         */
480        @Deprecated
481        public static byte[] toByteArray(String input) throws IOException {
482            return input.getBytes();
483        }
484    
485        // read char[]
486        //-----------------------------------------------------------------------
487        /**
488         * Get the contents of an <code>InputStream</code> as a character array
489         * using the default character encoding of the platform.
490         * <p>
491         * This method buffers the input internally, so there is no need to use a
492         * <code>BufferedInputStream</code>.
493         * 
494         * @param is  the <code>InputStream</code> to read from
495         * @return the requested character array
496         * @throws NullPointerException if the input is null
497         * @throws IOException if an I/O error occurs
498         * @since Commons IO 1.1
499         */
500        public static char[] toCharArray(InputStream is) throws IOException {
501            CharArrayWriter output = new CharArrayWriter();
502            copy(is, output);
503            return output.toCharArray();
504        }
505    
506        /**
507         * Get the contents of an <code>InputStream</code> as a character array
508         * using the specified character encoding.
509         * <p>
510         * Character encoding names can be found at
511         * <a href="http://www.iana.org/assignments/character-sets">IANA</a>.
512         * <p>
513         * This method buffers the input internally, so there is no need to use a
514         * <code>BufferedInputStream</code>.
515         * 
516         * @param is  the <code>InputStream</code> to read from
517         * @param encoding  the encoding to use, null means platform default
518         * @return the requested character array
519         * @throws NullPointerException if the input is null
520         * @throws IOException if an I/O error occurs
521         * @since Commons IO 1.1
522         */
523        public static char[] toCharArray(InputStream is, String encoding)
524                throws IOException {
525            CharArrayWriter output = new CharArrayWriter();
526            copy(is, output, encoding);
527            return output.toCharArray();
528        }
529    
530        /**
531         * Get the contents of a <code>Reader</code> as a character array.
532         * <p>
533         * This method buffers the input internally, so there is no need to use a
534         * <code>BufferedReader</code>.
535         * 
536         * @param input  the <code>Reader</code> to read from
537         * @return the requested character array
538         * @throws NullPointerException if the input is null
539         * @throws IOException if an I/O error occurs
540         * @since Commons IO 1.1
541         */
542        public static char[] toCharArray(Reader input) throws IOException {
543            CharArrayWriter sw = new CharArrayWriter();
544            copy(input, sw);
545            return sw.toCharArray();
546        }
547    
548        // read toString
549        //-----------------------------------------------------------------------
550        /**
551         * Get the contents of an <code>InputStream</code> as a String
552         * using the default character encoding of the platform.
553         * <p>
554         * This method buffers the input internally, so there is no need to use a
555         * <code>BufferedInputStream</code>.
556         * 
557         * @param input  the <code>InputStream</code> to read from
558         * @return the requested String
559         * @throws NullPointerException if the input is null
560         * @throws IOException if an I/O error occurs
561         */
562        public static String toString(InputStream input) throws IOException {
563            return toString(input, null);
564        }
565    
566        /**
567         * Get the contents of an <code>InputStream</code> as a String
568         * using the specified character encoding.
569         * <p>
570         * Character encoding names can be found at
571         * <a href="http://www.iana.org/assignments/character-sets">IANA</a>.
572         * <p>
573         * This method buffers the input internally, so there is no need to use a
574         * <code>BufferedInputStream</code>.
575         * 
576         * @param input  the <code>InputStream</code> to read from
577         * @param encoding  the encoding to use, null means platform default
578         * @return the requested String
579         * @throws NullPointerException if the input is null
580         * @throws IOException if an I/O error occurs
581         */
582        public static String toString(InputStream input, String encoding)
583                throws IOException {
584            StringBuilderWriter sw = new StringBuilderWriter();
585            copy(input, sw, encoding);
586            return sw.toString();
587        }
588    
589        /**
590         * Get the contents of a <code>Reader</code> as a String.
591         * <p>
592         * This method buffers the input internally, so there is no need to use a
593         * <code>BufferedReader</code>.
594         * 
595         * @param input  the <code>Reader</code> to read from
596         * @return the requested String
597         * @throws NullPointerException if the input is null
598         * @throws IOException if an I/O error occurs
599         */
600        public static String toString(Reader input) throws IOException {
601            StringBuilderWriter sw = new StringBuilderWriter();
602            copy(input, sw);
603            return sw.toString();
604        }
605    
606        /**
607         * Gets the contents at the given URI.
608         * 
609         * @param uri
610         *            The URI source.
611         * @return The contents of the URL as a String.
612         * @throws IOException if an I/O exception occurs.
613         * @since 2.1.
614         */
615        public static String toString(URI uri) throws IOException {
616            return toString(uri, null);
617        }
618    
619        /**
620         * Gets the contents at the given URI.
621         * 
622         * @param uri
623         *            The URI source.
624         * @param encoding
625         *            The encoding name for the URL contents.
626         * @return The contents of the URL as a String.
627         * @throws IOException if an I/O exception occurs.
628         * @since 2.1.
629         */
630        public static String toString(URI uri, String encoding) throws IOException {
631            return toString(uri.toURL(), encoding);
632        }
633    
634        /**
635         * Gets the contents at the given URL.
636         * 
637         * @param url
638         *            The URL source.
639         * @return The contents of the URL as a String.
640         * @throws IOException if an I/O exception occurs.
641         * @since 2.1.
642         */
643        public static String toString(URL url) throws IOException {
644            return toString(url, null);
645        }
646    
647        /**
648         * Gets the contents at the given URL.
649         * 
650         * @param url
651         *            The URL source.
652         * @param encoding
653         *            The encoding name for the URL contents.
654         * @return The contents of the URL as a String.
655         * @throws IOException if an I/O exception occurs.
656         * @since 2.1.
657         */
658        public static String toString(URL url, String encoding) throws IOException {
659            InputStream inputStream = url.openStream();
660            try {
661                return toString(inputStream, encoding);
662            } finally {
663                inputStream.close();
664            }
665        }
666    
667        /**
668         * Get the contents of a <code>byte[]</code> as a String
669         * using the default character encoding of the platform.
670         * 
671         * @param input the byte array to read from
672         * @return the requested String
673         * @throws NullPointerException if the input is null
674         * @throws IOException if an I/O error occurs (never occurs)
675         * @deprecated Use {@link String#String(byte[])}
676         */
677        @Deprecated
678        public static String toString(byte[] input) throws IOException {
679            return new String(input);
680        }
681    
682        /**
683         * Get the contents of a <code>byte[]</code> as a String
684         * using the specified character encoding.
685         * <p>
686         * Character encoding names can be found at
687         * <a href="http://www.iana.org/assignments/character-sets">IANA</a>.
688         * 
689         * @param input the byte array to read from
690         * @param encoding  the encoding to use, null means platform default
691         * @return the requested String
692         * @throws NullPointerException if the input is null
693         * @throws IOException if an I/O error occurs (never occurs)
694         * @deprecated Use {@link String#String(byte[],String)}
695         */
696        @Deprecated
697        public static String toString(byte[] input, String encoding)
698                throws IOException {
699            if (encoding == null) {
700                return new String(input);
701            } else {
702                return new String(input, encoding);
703            }
704        }
705    
706        // readLines
707        //-----------------------------------------------------------------------
708        /**
709         * Get the contents of an <code>InputStream</code> as a list of Strings,
710         * one entry per line, using the default character encoding of the platform.
711         * <p>
712         * This method buffers the input internally, so there is no need to use a
713         * <code>BufferedInputStream</code>.
714         *
715         * @param input  the <code>InputStream</code> to read from, not null
716         * @return the list of Strings, never null
717         * @throws NullPointerException if the input is null
718         * @throws IOException if an I/O error occurs
719         * @since Commons IO 1.1
720         */
721        public static List<String> readLines(InputStream input) throws IOException {
722            InputStreamReader reader = new InputStreamReader(input);
723            return readLines(reader);
724        }
725    
726        /**
727         * Get the contents of an <code>InputStream</code> as a list of Strings,
728         * one entry per line, using the specified character encoding.
729         * <p>
730         * Character encoding names can be found at
731         * <a href="http://www.iana.org/assignments/character-sets">IANA</a>.
732         * <p>
733         * This method buffers the input internally, so there is no need to use a
734         * <code>BufferedInputStream</code>.
735         *
736         * @param input  the <code>InputStream</code> to read from, not null
737         * @param encoding  the encoding to use, null means platform default
738         * @return the list of Strings, never null
739         * @throws NullPointerException if the input is null
740         * @throws IOException if an I/O error occurs
741         * @since Commons IO 1.1
742         */
743        public static List<String> readLines(InputStream input, String encoding) throws IOException {
744            if (encoding == null) {
745                return readLines(input);
746            } else {
747                InputStreamReader reader = new InputStreamReader(input, encoding);
748                return readLines(reader);
749            }
750        }
751    
752        /**
753         * Get the contents of a <code>Reader</code> as a list of Strings,
754         * one entry per line.
755         * <p>
756         * This method buffers the input internally, so there is no need to use a
757         * <code>BufferedReader</code>.
758         *
759         * @param input  the <code>Reader</code> to read from, not null
760         * @return the list of Strings, never null
761         * @throws NullPointerException if the input is null
762         * @throws IOException if an I/O error occurs
763         * @since Commons IO 1.1
764         */
765        public static List<String> readLines(Reader input) throws IOException {
766            BufferedReader reader = new BufferedReader(input);
767            List<String> list = new ArrayList<String>();
768            String line = reader.readLine();
769            while (line != null) {
770                list.add(line);
771                line = reader.readLine();
772            }
773            return list;
774        }
775    
776        // lineIterator
777        //-----------------------------------------------------------------------
778        /**
779         * Return an Iterator for the lines in a <code>Reader</code>.
780         * <p>
781         * <code>LineIterator</code> holds a reference to the open
782         * <code>Reader</code> specified here. When you have finished with the
783         * iterator you should close the reader to free internal resources.
784         * This can be done by closing the reader directly, or by calling
785         * {@link LineIterator#close()} or {@link LineIterator#closeQuietly(LineIterator)}.
786         * <p>
787         * The recommended usage pattern is:
788         * <pre>
789         * try {
790         *   LineIterator it = IOUtils.lineIterator(reader);
791         *   while (it.hasNext()) {
792         *     String line = it.nextLine();
793         *     /// do something with line
794         *   }
795         * } finally {
796         *   IOUtils.closeQuietly(reader);
797         * }
798         * </pre>
799         *
800         * @param reader  the <code>Reader</code> to read from, not null
801         * @return an Iterator of the lines in the reader, never null
802         * @throws IllegalArgumentException if the reader is null
803         * @since Commons IO 1.2
804         */
805        public static LineIterator lineIterator(Reader reader) {
806            return new LineIterator(reader);
807        }
808    
809        /**
810         * Return an Iterator for the lines in an <code>InputStream</code>, using
811         * the character encoding specified (or default encoding if null).
812         * <p>
813         * <code>LineIterator</code> holds a reference to the open
814         * <code>InputStream</code> specified here. When you have finished with
815         * the iterator you should close the stream to free internal resources.
816         * This can be done by closing the stream directly, or by calling
817         * {@link LineIterator#close()} or {@link LineIterator#closeQuietly(LineIterator)}.
818         * <p>
819         * The recommended usage pattern is:
820         * <pre>
821         * try {
822         *   LineIterator it = IOUtils.lineIterator(stream, "UTF-8");
823         *   while (it.hasNext()) {
824         *     String line = it.nextLine();
825         *     /// do something with line
826         *   }
827         * } finally {
828         *   IOUtils.closeQuietly(stream);
829         * }
830         * </pre>
831         *
832         * @param input  the <code>InputStream</code> to read from, not null
833         * @param encoding  the encoding to use, null means platform default
834         * @return an Iterator of the lines in the reader, never null
835         * @throws IllegalArgumentException if the input is null
836         * @throws IOException if an I/O error occurs, such as if the encoding is invalid
837         * @since Commons IO 1.2
838         */
839        public static LineIterator lineIterator(InputStream input, String encoding) 
840                         throws IOException {
841            Reader reader = null;
842            if (encoding == null) {
843                reader = new InputStreamReader(input);
844            } else {
845                reader = new InputStreamReader(input, encoding);
846            }
847            return new LineIterator(reader);
848        }
849    
850        //-----------------------------------------------------------------------
851        /**
852         * Convert the specified CharSequence to an input stream, encoded as bytes
853         * using the default character encoding of the platform.
854         *
855         * @param input the CharSequence to convert
856         * @return an input stream
857         * @since Commons IO 2.0
858         */
859        public static InputStream toInputStream(CharSequence input) {
860            return toInputStream(input.toString());
861        }
862    
863        /**
864         * Convert the specified CharSequence to an input stream, encoded as bytes
865         * using the specified character encoding.
866         * <p>
867         * Character encoding names can be found at
868         * <a href="http://www.iana.org/assignments/character-sets">IANA</a>.
869         *
870         * @param input the CharSequence to convert
871         * @param encoding the encoding to use, null means platform default
872         * @throws IOException if the encoding is invalid
873         * @return an input stream
874         * @since Commons IO 2.0
875         */
876        public static InputStream toInputStream(CharSequence input, String encoding) throws IOException {
877            return toInputStream(input.toString(), encoding);
878        }
879    
880        //-----------------------------------------------------------------------
881        /**
882         * Convert the specified string to an input stream, encoded as bytes
883         * using the default character encoding of the platform.
884         *
885         * @param input the string to convert
886         * @return an input stream
887         * @since Commons IO 1.1
888         */
889        public static InputStream toInputStream(String input) {
890            byte[] bytes = input.getBytes();
891            return new ByteArrayInputStream(bytes);
892        }
893    
894        /**
895         * Convert the specified string to an input stream, encoded as bytes
896         * using the specified character encoding.
897         * <p>
898         * Character encoding names can be found at
899         * <a href="http://www.iana.org/assignments/character-sets">IANA</a>.
900         *
901         * @param input the string to convert
902         * @param encoding the encoding to use, null means platform default
903         * @throws IOException if the encoding is invalid
904         * @return an input stream
905         * @since Commons IO 1.1
906         */
907        public static InputStream toInputStream(String input, String encoding) throws IOException {
908            byte[] bytes = encoding != null ? input.getBytes(encoding) : input.getBytes();
909            return new ByteArrayInputStream(bytes);
910        }
911    
912        // write byte[]
913        //-----------------------------------------------------------------------
914        /**
915         * Writes bytes from a <code>byte[]</code> to an <code>OutputStream</code>.
916         * 
917         * @param data  the byte array to write, do not modify during output,
918         * null ignored
919         * @param output  the <code>OutputStream</code> to write to
920         * @throws NullPointerException if output is null
921         * @throws IOException if an I/O error occurs
922         * @since Commons IO 1.1
923         */
924        public static void write(byte[] data, OutputStream output)
925                throws IOException {
926            if (data != null) {
927                output.write(data);
928            }
929        }
930    
931        /**
932         * Writes bytes from a <code>byte[]</code> to chars on a <code>Writer</code>
933         * using the default character encoding of the platform.
934         * <p>
935         * This method uses {@link String#String(byte[])}.
936         * 
937         * @param data  the byte array to write, do not modify during output,
938         * null ignored
939         * @param output  the <code>Writer</code> to write to
940         * @throws NullPointerException if output is null
941         * @throws IOException if an I/O error occurs
942         * @since Commons IO 1.1
943         */
944        public static void write(byte[] data, Writer output) throws IOException {
945            if (data != null) {
946                output.write(new String(data));
947            }
948        }
949    
950        /**
951         * Writes bytes from a <code>byte[]</code> to chars on a <code>Writer</code>
952         * using the specified character encoding.
953         * <p>
954         * Character encoding names can be found at
955         * <a href="http://www.iana.org/assignments/character-sets">IANA</a>.
956         * <p>
957         * This method uses {@link String#String(byte[], String)}.
958         * 
959         * @param data  the byte array to write, do not modify during output,
960         * null ignored
961         * @param output  the <code>Writer</code> to write to
962         * @param encoding  the encoding to use, null means platform default
963         * @throws NullPointerException if output is null
964         * @throws IOException if an I/O error occurs
965         * @since Commons IO 1.1
966         */
967        public static void write(byte[] data, Writer output, String encoding)
968                throws IOException {
969            if (data != null) {
970                if (encoding == null) {
971                    write(data, output);
972                } else {
973                    output.write(new String(data, encoding));
974                }
975            }
976        }
977    
978        // write char[]
979        //-----------------------------------------------------------------------
980        /**
981         * Writes chars from a <code>char[]</code> to a <code>Writer</code>
982         * using the default character encoding of the platform.
983         * 
984         * @param data  the char array to write, do not modify during output,
985         * null ignored
986         * @param output  the <code>Writer</code> to write to
987         * @throws NullPointerException if output is null
988         * @throws IOException if an I/O error occurs
989         * @since Commons IO 1.1
990         */
991        public static void write(char[] data, Writer output) throws IOException {
992            if (data != null) {
993                output.write(data);
994            }
995        }
996    
997        /**
998         * Writes chars from a <code>char[]</code> to bytes on an
999         * <code>OutputStream</code>.
1000         * <p>
1001         * This method uses {@link String#String(char[])} and
1002         * {@link String#getBytes()}.
1003         * 
1004         * @param data  the char array to write, do not modify during output,
1005         * null ignored
1006         * @param output  the <code>OutputStream</code> to write to
1007         * @throws NullPointerException if output is null
1008         * @throws IOException if an I/O error occurs
1009         * @since Commons IO 1.1
1010         */
1011        public static void write(char[] data, OutputStream output)
1012                throws IOException {
1013            if (data != null) {
1014                output.write(new String(data).getBytes());
1015            }
1016        }
1017    
1018        /**
1019         * Writes chars from a <code>char[]</code> to bytes on an
1020         * <code>OutputStream</code> using the specified character encoding.
1021         * <p>
1022         * Character encoding names can be found at
1023         * <a href="http://www.iana.org/assignments/character-sets">IANA</a>.
1024         * <p>
1025         * This method uses {@link String#String(char[])} and
1026         * {@link String#getBytes(String)}.
1027         * 
1028         * @param data  the char array to write, do not modify during output,
1029         * null ignored
1030         * @param output  the <code>OutputStream</code> to write to
1031         * @param encoding  the encoding to use, null means platform default
1032         * @throws NullPointerException if output is null
1033         * @throws IOException if an I/O error occurs
1034         * @since Commons IO 1.1
1035         */
1036        public static void write(char[] data, OutputStream output, String encoding)
1037                throws IOException {
1038            if (data != null) {
1039                if (encoding == null) {
1040                    write(data, output);
1041                } else {
1042                    output.write(new String(data).getBytes(encoding));
1043                }
1044            }
1045        }
1046    
1047        // write CharSequence
1048        //-----------------------------------------------------------------------
1049        /**
1050         * Writes chars from a <code>CharSequence</code> to a <code>Writer</code>.
1051         * 
1052         * @param data  the <code>CharSequence</code> to write, null ignored
1053         * @param output  the <code>Writer</code> to write to
1054         * @throws NullPointerException if output is null
1055         * @throws IOException if an I/O error occurs
1056         * @since Commons IO 2.0
1057         */
1058        public static void write(CharSequence data, Writer output) throws IOException {
1059            if (data != null) {
1060                write(data.toString(), output);
1061            }
1062        }
1063    
1064        /**
1065         * Writes chars from a <code>CharSequence</code> to bytes on an
1066         * <code>OutputStream</code> using the default character encoding of the
1067         * platform.
1068         * <p>
1069         * This method uses {@link String#getBytes()}.
1070         * 
1071         * @param data  the <code>CharSequence</code> to write, null ignored
1072         * @param output  the <code>OutputStream</code> to write to
1073         * @throws NullPointerException if output is null
1074         * @throws IOException if an I/O error occurs
1075         * @since Commons IO 2.0
1076         */
1077        public static void write(CharSequence data, OutputStream output)
1078                throws IOException {
1079            if (data != null) {
1080                write(data.toString(), output);
1081            }
1082        }
1083    
1084        /**
1085         * Writes chars from a <code>CharSequence</code> to bytes on an
1086         * <code>OutputStream</code> using the specified character encoding.
1087         * <p>
1088         * Character encoding names can be found at
1089         * <a href="http://www.iana.org/assignments/character-sets">IANA</a>.
1090         * <p>
1091         * This method uses {@link String#getBytes(String)}.
1092         * 
1093         * @param data  the <code>CharSequence</code> to write, null ignored
1094         * @param output  the <code>OutputStream</code> to write to
1095         * @param encoding  the encoding to use, null means platform default
1096         * @throws NullPointerException if output is null
1097         * @throws IOException if an I/O error occurs
1098         * @since Commons IO 2.0
1099         */
1100        public static void write(CharSequence data, OutputStream output, String encoding)
1101                throws IOException {
1102            if (data != null) {
1103                write(data.toString(), output, encoding);
1104            }
1105        }
1106    
1107        // write String
1108        //-----------------------------------------------------------------------
1109        /**
1110         * Writes chars from a <code>String</code> to a <code>Writer</code>.
1111         * 
1112         * @param data  the <code>String</code> to write, null ignored
1113         * @param output  the <code>Writer</code> to write to
1114         * @throws NullPointerException if output is null
1115         * @throws IOException if an I/O error occurs
1116         * @since Commons IO 1.1
1117         */
1118        public static void write(String data, Writer output) throws IOException {
1119            if (data != null) {
1120                output.write(data);
1121            }
1122        }
1123    
1124        /**
1125         * Writes chars from a <code>String</code> to bytes on an
1126         * <code>OutputStream</code> using the default character encoding of the
1127         * platform.
1128         * <p>
1129         * This method uses {@link String#getBytes()}.
1130         * 
1131         * @param data  the <code>String</code> to write, null ignored
1132         * @param output  the <code>OutputStream</code> to write to
1133         * @throws NullPointerException if output is null
1134         * @throws IOException if an I/O error occurs
1135         * @since Commons IO 1.1
1136         */
1137        public static void write(String data, OutputStream output)
1138                throws IOException {
1139            if (data != null) {
1140                output.write(data.getBytes());
1141            }
1142        }
1143    
1144        /**
1145         * Writes chars from a <code>String</code> to bytes on an
1146         * <code>OutputStream</code> using the specified character encoding.
1147         * <p>
1148         * Character encoding names can be found at
1149         * <a href="http://www.iana.org/assignments/character-sets">IANA</a>.
1150         * <p>
1151         * This method uses {@link String#getBytes(String)}.
1152         * 
1153         * @param data  the <code>String</code> to write, null ignored
1154         * @param output  the <code>OutputStream</code> to write to
1155         * @param encoding  the encoding to use, null means platform default
1156         * @throws NullPointerException if output is null
1157         * @throws IOException if an I/O error occurs
1158         * @since Commons IO 1.1
1159         */
1160        public static void write(String data, OutputStream output, String encoding)
1161                throws IOException {
1162            if (data != null) {
1163                if (encoding == null) {
1164                    write(data, output);
1165                } else {
1166                    output.write(data.getBytes(encoding));
1167                }
1168            }
1169        }
1170    
1171        // write StringBuffer
1172        //-----------------------------------------------------------------------
1173        /**
1174         * Writes chars from a <code>StringBuffer</code> to a <code>Writer</code>.
1175         * 
1176         * @param data  the <code>StringBuffer</code> to write, null ignored
1177         * @param output  the <code>Writer</code> to write to
1178         * @throws NullPointerException if output is null
1179         * @throws IOException if an I/O error occurs
1180         * @since Commons IO 1.1
1181         * @deprecated replaced by write(CharSequence, Writer)
1182         */
1183        @Deprecated
1184        public static void write(StringBuffer data, Writer output)
1185                throws IOException {
1186            if (data != null) {
1187                output.write(data.toString());
1188            }
1189        }
1190    
1191        /**
1192         * Writes chars from a <code>StringBuffer</code> to bytes on an
1193         * <code>OutputStream</code> using the default character encoding of the
1194         * platform.
1195         * <p>
1196         * This method uses {@link String#getBytes()}.
1197         * 
1198         * @param data  the <code>StringBuffer</code> to write, null ignored
1199         * @param output  the <code>OutputStream</code> to write to
1200         * @throws NullPointerException if output is null
1201         * @throws IOException if an I/O error occurs
1202         * @since Commons IO 1.1
1203         * @deprecated replaced by write(CharSequence, OutputStream)
1204         */
1205        @Deprecated
1206        public static void write(StringBuffer data, OutputStream output)
1207                throws IOException {
1208            if (data != null) {
1209                output.write(data.toString().getBytes());
1210            }
1211        }
1212    
1213        /**
1214         * Writes chars from a <code>StringBuffer</code> to bytes on an
1215         * <code>OutputStream</code> using the specified character encoding.
1216         * <p>
1217         * Character encoding names can be found at
1218         * <a href="http://www.iana.org/assignments/character-sets">IANA</a>.
1219         * <p>
1220         * This method uses {@link String#getBytes(String)}.
1221         * 
1222         * @param data  the <code>StringBuffer</code> to write, null ignored
1223         * @param output  the <code>OutputStream</code> to write to
1224         * @param encoding  the encoding to use, null means platform default
1225         * @throws NullPointerException if output is null
1226         * @throws IOException if an I/O error occurs
1227         * @since Commons IO 1.1
1228         * @deprecated replaced by write(CharSequence, OutputStream, String)
1229         */
1230        @Deprecated
1231        public static void write(StringBuffer data, OutputStream output,
1232                String encoding) throws IOException {
1233            if (data != null) {
1234                if (encoding == null) {
1235                    write(data, output);
1236                } else {
1237                    output.write(data.toString().getBytes(encoding));
1238                }
1239            }
1240        }
1241    
1242        // writeLines
1243        //-----------------------------------------------------------------------
1244        /**
1245         * Writes the <code>toString()</code> value of each item in a collection to
1246         * an <code>OutputStream</code> line by line, using the default character
1247         * encoding of the platform and the specified line ending.
1248         *
1249         * @param lines  the lines to write, null entries produce blank lines
1250         * @param lineEnding  the line separator to use, null is system default
1251         * @param output  the <code>OutputStream</code> to write to, not null, not closed
1252         * @throws NullPointerException if the output is null
1253         * @throws IOException if an I/O error occurs
1254         * @since Commons IO 1.1
1255         */
1256        public static void writeLines(Collection<?> lines, String lineEnding,
1257                OutputStream output) throws IOException {
1258            if (lines == null) {
1259                return;
1260            }
1261            if (lineEnding == null) {
1262                lineEnding = LINE_SEPARATOR;
1263            }
1264            for (Object line : lines) {
1265                if (line != null) {
1266                    output.write(line.toString().getBytes());
1267                }
1268                output.write(lineEnding.getBytes());
1269            }
1270        }
1271    
1272        /**
1273         * Writes the <code>toString()</code> value of each item in a collection to
1274         * an <code>OutputStream</code> line by line, using the specified character
1275         * encoding and the specified line ending.
1276         * <p>
1277         * Character encoding names can be found at
1278         * <a href="http://www.iana.org/assignments/character-sets">IANA</a>.
1279         *
1280         * @param lines  the lines to write, null entries produce blank lines
1281         * @param lineEnding  the line separator to use, null is system default
1282         * @param output  the <code>OutputStream</code> to write to, not null, not closed
1283         * @param encoding  the encoding to use, null means platform default
1284         * @throws NullPointerException if the output is null
1285         * @throws IOException if an I/O error occurs
1286         * @since Commons IO 1.1
1287         */
1288        public static void writeLines(Collection<?> lines, String lineEnding,
1289                OutputStream output, String encoding) throws IOException {
1290            if (encoding == null) {
1291                writeLines(lines, lineEnding, output);
1292            } else {
1293                if (lines == null) {
1294                    return;
1295                }
1296                if (lineEnding == null) {
1297                    lineEnding = LINE_SEPARATOR;
1298                }
1299                for (Object line : lines) {
1300                    if (line != null) {
1301                        output.write(line.toString().getBytes(encoding));
1302                    }
1303                    output.write(lineEnding.getBytes(encoding));
1304                }
1305            }
1306        }
1307    
1308        /**
1309         * Writes the <code>toString()</code> value of each item in a collection to
1310         * a <code>Writer</code> line by line, using the specified line ending.
1311         *
1312         * @param lines  the lines to write, null entries produce blank lines
1313         * @param lineEnding  the line separator to use, null is system default
1314         * @param writer  the <code>Writer</code> to write to, not null, not closed
1315         * @throws NullPointerException if the input is null
1316         * @throws IOException if an I/O error occurs
1317         * @since Commons IO 1.1
1318         */
1319        public static void writeLines(Collection<?> lines, String lineEnding,
1320                Writer writer) throws IOException {
1321            if (lines == null) {
1322                return;
1323            }
1324            if (lineEnding == null) {
1325                lineEnding = LINE_SEPARATOR;
1326            }
1327            for (Object line : lines) {
1328                if (line != null) {
1329                    writer.write(line.toString());
1330                }
1331                writer.write(lineEnding);
1332            }
1333        }
1334    
1335        // copy from InputStream
1336        //-----------------------------------------------------------------------
1337        /**
1338         * Copy bytes from an <code>InputStream</code> to an
1339         * <code>OutputStream</code>.
1340         * <p>
1341         * This method buffers the input internally, so there is no need to use a
1342         * <code>BufferedInputStream</code>.
1343         * <p>
1344         * Large streams (over 2GB) will return a bytes copied value of
1345         * <code>-1</code> after the copy has completed since the correct
1346         * number of bytes cannot be returned as an int. For large streams
1347         * use the <code>copyLarge(InputStream, OutputStream)</code> method.
1348         * 
1349         * @param input  the <code>InputStream</code> to read from
1350         * @param output  the <code>OutputStream</code> to write to
1351         * @return the number of bytes copied, or -1 if &gt; Integer.MAX_VALUE
1352         * @throws NullPointerException if the input or output is null
1353         * @throws IOException if an I/O error occurs
1354         * @since Commons IO 1.1
1355         */
1356        public static int copy(InputStream input, OutputStream output) throws IOException {
1357            long count = copyLarge(input, output);
1358            if (count > Integer.MAX_VALUE) {
1359                return -1;
1360            }
1361            return (int) count;
1362        }
1363    
1364        /**
1365         * Copy bytes from a large (over 2GB) <code>InputStream</code> to an
1366         * <code>OutputStream</code>.
1367         * <p>
1368         * This method buffers the input internally, so there is no need to use a
1369         * <code>BufferedInputStream</code>.
1370         * 
1371         * @param input  the <code>InputStream</code> to read from
1372         * @param output  the <code>OutputStream</code> to write to
1373         * @return the number of bytes copied
1374         * @throws NullPointerException if the input or output is null
1375         * @throws IOException if an I/O error occurs
1376         * @since Commons IO 1.3
1377         */
1378        public static long copyLarge(InputStream input, OutputStream output)
1379                throws IOException {
1380            byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
1381            long count = 0;
1382            int n = 0;
1383            while (-1 != (n = input.read(buffer))) {
1384                output.write(buffer, 0, n);
1385                count += n;
1386            }
1387            return count;
1388        }
1389    
1390        /**
1391         * Copy bytes from an <code>InputStream</code> to chars on a
1392         * <code>Writer</code> using the default character encoding of the platform.
1393         * <p>
1394         * This method buffers the input internally, so there is no need to use a
1395         * <code>BufferedInputStream</code>.
1396         * <p>
1397         * This method uses {@link InputStreamReader}.
1398         *
1399         * @param input  the <code>InputStream</code> to read from
1400         * @param output  the <code>Writer</code> to write to
1401         * @throws NullPointerException if the input or output is null
1402         * @throws IOException if an I/O error occurs
1403         * @since Commons IO 1.1
1404         */
1405        public static void copy(InputStream input, Writer output)
1406                throws IOException {
1407            InputStreamReader in = new InputStreamReader(input);
1408            copy(in, output);
1409        }
1410    
1411        /**
1412         * Copy bytes from an <code>InputStream</code> to chars on a
1413         * <code>Writer</code> using the specified character encoding.
1414         * <p>
1415         * This method buffers the input internally, so there is no need to use a
1416         * <code>BufferedInputStream</code>.
1417         * <p>
1418         * Character encoding names can be found at
1419         * <a href="http://www.iana.org/assignments/character-sets">IANA</a>.
1420         * <p>
1421         * This method uses {@link InputStreamReader}.
1422         *
1423         * @param input  the <code>InputStream</code> to read from
1424         * @param output  the <code>Writer</code> to write to
1425         * @param encoding  the encoding to use, null means platform default
1426         * @throws NullPointerException if the input or output is null
1427         * @throws IOException if an I/O error occurs
1428         * @since Commons IO 1.1
1429         */
1430        public static void copy(InputStream input, Writer output, String encoding)
1431                throws IOException {
1432            if (encoding == null) {
1433                copy(input, output);
1434            } else {
1435                InputStreamReader in = new InputStreamReader(input, encoding);
1436                copy(in, output);
1437            }
1438        }
1439    
1440        // copy from Reader
1441        //-----------------------------------------------------------------------
1442        /**
1443         * Copy chars from a <code>Reader</code> to a <code>Writer</code>.
1444         * <p>
1445         * This method buffers the input internally, so there is no need to use a
1446         * <code>BufferedReader</code>.
1447         * <p>
1448         * Large streams (over 2GB) will return a chars copied value of
1449         * <code>-1</code> after the copy has completed since the correct
1450         * number of chars cannot be returned as an int. For large streams
1451         * use the <code>copyLarge(Reader, Writer)</code> method.
1452         *
1453         * @param input  the <code>Reader</code> to read from
1454         * @param output  the <code>Writer</code> to write to
1455         * @return the number of characters copied, or -1 if &gt; Integer.MAX_VALUE
1456         * @throws NullPointerException if the input or output is null
1457         * @throws IOException if an I/O error occurs
1458         * @since Commons IO 1.1
1459         */
1460        public static int copy(Reader input, Writer output) throws IOException {
1461            long count = copyLarge(input, output);
1462            if (count > Integer.MAX_VALUE) {
1463                return -1;
1464            }
1465            return (int) count;
1466        }
1467    
1468        /**
1469         * Copy chars from a large (over 2GB) <code>Reader</code> to a <code>Writer</code>.
1470         * <p>
1471         * This method buffers the input internally, so there is no need to use a
1472         * <code>BufferedReader</code>.
1473         *
1474         * @param input  the <code>Reader</code> to read from
1475         * @param output  the <code>Writer</code> to write to
1476         * @return the number of characters copied
1477         * @throws NullPointerException if the input or output is null
1478         * @throws IOException if an I/O error occurs
1479         * @since Commons IO 1.3
1480         */
1481        public static long copyLarge(Reader input, Writer output) throws IOException {
1482            char[] buffer = new char[DEFAULT_BUFFER_SIZE];
1483            long count = 0;
1484            int n = 0;
1485            while (-1 != (n = input.read(buffer))) {
1486                output.write(buffer, 0, n);
1487                count += n;
1488            }
1489            return count;
1490        }
1491    
1492        /**
1493         * Copy chars from a <code>Reader</code> to bytes on an
1494         * <code>OutputStream</code> using the default character encoding of the
1495         * platform, and calling flush.
1496         * <p>
1497         * This method buffers the input internally, so there is no need to use a
1498         * <code>BufferedReader</code>.
1499         * <p>
1500         * Due to the implementation of OutputStreamWriter, this method performs a
1501         * flush.
1502         * <p>
1503         * This method uses {@link OutputStreamWriter}.
1504         *
1505         * @param input  the <code>Reader</code> to read from
1506         * @param output  the <code>OutputStream</code> to write to
1507         * @throws NullPointerException if the input or output is null
1508         * @throws IOException if an I/O error occurs
1509         * @since Commons IO 1.1
1510         */
1511        public static void copy(Reader input, OutputStream output)
1512                throws IOException {
1513            OutputStreamWriter out = new OutputStreamWriter(output);
1514            copy(input, out);
1515            // XXX Unless anyone is planning on rewriting OutputStreamWriter, we
1516            // have to flush here.
1517            out.flush();
1518        }
1519    
1520        /**
1521         * Copy chars from a <code>Reader</code> to bytes on an
1522         * <code>OutputStream</code> using the specified character encoding, and
1523         * calling flush.
1524         * <p>
1525         * This method buffers the input internally, so there is no need to use a
1526         * <code>BufferedReader</code>.
1527         * <p>
1528         * Character encoding names can be found at
1529         * <a href="http://www.iana.org/assignments/character-sets">IANA</a>.
1530         * <p>
1531         * Due to the implementation of OutputStreamWriter, this method performs a
1532         * flush.
1533         * <p>
1534         * This method uses {@link OutputStreamWriter}.
1535         *
1536         * @param input  the <code>Reader</code> to read from
1537         * @param output  the <code>OutputStream</code> to write to
1538         * @param encoding  the encoding to use, null means platform default
1539         * @throws NullPointerException if the input or output is null
1540         * @throws IOException if an I/O error occurs
1541         * @since Commons IO 1.1
1542         */
1543        public static void copy(Reader input, OutputStream output, String encoding)
1544                throws IOException {
1545            if (encoding == null) {
1546                copy(input, output);
1547            } else {
1548                OutputStreamWriter out = new OutputStreamWriter(output, encoding);
1549                copy(input, out);
1550                // XXX Unless anyone is planning on rewriting OutputStreamWriter,
1551                // we have to flush here.
1552                out.flush();
1553            }
1554        }
1555    
1556        // content equals
1557        //-----------------------------------------------------------------------
1558        /**
1559         * Compare the contents of two Streams to determine if they are equal or
1560         * not.
1561         * <p>
1562         * This method buffers the input internally using
1563         * <code>BufferedInputStream</code> if they are not already buffered.
1564         *
1565         * @param input1  the first stream
1566         * @param input2  the second stream
1567         * @return true if the content of the streams are equal or they both don't
1568         * exist, false otherwise
1569         * @throws NullPointerException if either input is null
1570         * @throws IOException if an I/O error occurs
1571         */
1572        public static boolean contentEquals(InputStream input1, InputStream input2)
1573                throws IOException {
1574            if (!(input1 instanceof BufferedInputStream)) {
1575                input1 = new BufferedInputStream(input1);
1576            }
1577            if (!(input2 instanceof BufferedInputStream)) {
1578                input2 = new BufferedInputStream(input2);
1579            }
1580    
1581            int ch = input1.read();
1582            while (-1 != ch) {
1583                int ch2 = input2.read();
1584                if (ch != ch2) {
1585                    return false;
1586                }
1587                ch = input1.read();
1588            }
1589    
1590            int ch2 = input2.read();
1591            return (ch2 == -1);
1592        }
1593    
1594        /**
1595         * Compare the contents of two Readers to determine if they are equal or
1596         * not.
1597         * <p>
1598         * This method buffers the input internally using
1599         * <code>BufferedReader</code> if they are not already buffered.
1600         *
1601         * @param input1  the first reader
1602         * @param input2  the second reader
1603         * @return true if the content of the readers are equal or they both don't
1604         * exist, false otherwise
1605         * @throws NullPointerException if either input is null
1606         * @throws IOException if an I/O error occurs
1607         * @since Commons IO 1.1
1608         */
1609        public static boolean contentEquals(Reader input1, Reader input2)
1610                throws IOException {
1611            if (!(input1 instanceof BufferedReader)) {
1612                input1 = new BufferedReader(input1);
1613            }
1614            if (!(input2 instanceof BufferedReader)) {
1615                input2 = new BufferedReader(input2);
1616            }
1617    
1618            int ch = input1.read();
1619            while (-1 != ch) {
1620                int ch2 = input2.read();
1621                if (ch != ch2) {
1622                    return false;
1623                }
1624                ch = input1.read();
1625            }
1626    
1627            int ch2 = input2.read();
1628            return (ch2 == -1);
1629        }
1630    
1631        /**
1632         * Skip bytes from an input byte stream.
1633         * This implementation guarantees that it will read as many bytes
1634         * as possible before giving up; this may not always be the case for
1635         * subclasses of {@link Reader}.
1636         *   
1637         * @param input byte stream to skip
1638         * @param toSkip number of bytes to skip.
1639         * @return number of bytes actually skipped.
1640         * 
1641         * @see InputStream#skip(long)
1642         * 
1643         * @throws IOException if there is a problem reading the file
1644         * @throws IllegalArgumentException if toSkip is negative
1645         * @since Commons IO 2.0
1646         */
1647        public static long skip(InputStream input, long toSkip) throws IOException {
1648            if (toSkip < 0) {
1649                throw new IllegalArgumentException("Skip count must be non-negative, actual: "+toSkip);
1650            }
1651            /*
1652             * N.B. no need to synchronize this because:
1653             * - we don't care if the buffer is created multiple times (the data is ignored)
1654             * - we always use the same size buffer, so if it it is recreated it will still be OK
1655             * (if the buffer size were variable, we would need to synch. to ensure some other thread
1656             * did not create a smaller one)
1657             */
1658            if (SKIP_BYTE_BUFFER == null){
1659                SKIP_BYTE_BUFFER = new byte[SKIP_BUFFER_SIZE];
1660            }
1661            long remain=toSkip;
1662            while(remain > 0) {
1663                long n = input.read(SKIP_BYTE_BUFFER, 0, (int) Math.min(remain, SKIP_BUFFER_SIZE));
1664                if (n < 0) { // EOF
1665                    break;
1666                }
1667                remain -= n;
1668            }
1669            return toSkip - remain;   
1670        }
1671    
1672        /**
1673         * Skip characters from an input character stream.
1674         * This implementation guarantees that it will read as many characters
1675         * as possible before giving up; this may not always be the case for
1676         * subclasses of {@link Reader}.
1677         *   
1678         * @param input character stream to skip
1679         * @param toSkip number of characters to skip.
1680         * @return number of characters actually skipped.
1681         * 
1682         * @see Reader#skip(long)
1683         * 
1684         * @throws IOException if there is a problem reading the file
1685         * @throws IllegalArgumentException if toSkip is negative
1686         * @since Commons IO 2.0
1687         */
1688        public static long skip(Reader input, long toSkip) throws IOException {
1689            if (toSkip < 0) {
1690                throw new IllegalArgumentException("Skip count must be non-negative, actual: "+toSkip);
1691            }
1692            /*
1693             * N.B. no need to synchronize this because:
1694             * - we don't care if the buffer is created multiple times (the data is ignored)
1695             * - we always use the same size buffer, so if it it is recreated it will still be OK
1696             * (if the buffer size were variable, we would need to synch. to ensure some other thread
1697             * did not create a smaller one)
1698             */
1699            if (SKIP_CHAR_BUFFER == null){
1700                SKIP_CHAR_BUFFER = new char[SKIP_BUFFER_SIZE];
1701            }
1702            long remain=toSkip;
1703            while(remain > 0) {
1704                long n = input.read(SKIP_CHAR_BUFFER, 0, (int) Math.min(remain, SKIP_BUFFER_SIZE));
1705                if (n < 0) { // EOF
1706                    break;
1707                }
1708                remain -= n;
1709            }
1710            return toSkip - remain;   
1711        }
1712    
1713        /**
1714         * Skip the requested number of bytes or fail if there are not enough left.
1715         * <p>
1716         * This allows for the possibility that {@link InputStream#skip(long)} may
1717         * not skip as many bytes as requested (most likely because of reaching EOF).
1718         * 
1719         * @param input stream to skip
1720         * @param toSkip the number of bytes to skip
1721         * @see InputStream#skip(long)
1722         * 
1723         * @throws IOException if there is a problem reading the file
1724         * @throws IllegalArgumentException if toSkip is negative
1725         * @throws EOFException if the number of bytes skipped was incorrect 
1726         * @since Commons IO 2.0
1727         */
1728        public static void skipFully(InputStream input, long toSkip) throws IOException {
1729            if (toSkip < 0){
1730                throw new IllegalArgumentException("Bytes to skip must not be negative: "+toSkip);
1731            }
1732            long skipped = skip(input, toSkip);
1733            if (skipped != toSkip) {
1734                throw new EOFException("Bytes to skip: "+toSkip+" actual: "+skipped);
1735            }
1736        }
1737    
1738        /**
1739         * Skip the requested number of characters or fail if there are not enough left.
1740         * <p>
1741         * This allows for the possibility that {@link Reader#skip(long)} may
1742         * not skip as many characters as requested (most likely because of reaching EOF).
1743         * 
1744         * @param input stream to skip
1745         * @param toSkip the number of characters to skip
1746         * @see Reader#skip(long)
1747         * 
1748         * @throws IOException if there is a problem reading the file
1749         * @throws IllegalArgumentException if toSkip is negative
1750         * @throws EOFException if the number of characters skipped was incorrect
1751         * @since Commons IO 2.0
1752         */
1753        public static void skipFully(Reader input, long toSkip) throws IOException {
1754            long skipped = skip(input, toSkip);
1755            if (skipped != toSkip) {
1756                throw new EOFException("Bytes to skip: "+toSkip+" actual: "+skipped);
1757            }
1758        }
1759    }