View Javadoc

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