View Javadoc
1   package org.apache.maven.shared.utils.io;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import javax.annotation.Nonnull;
23  import javax.annotation.Nullable;
24  
25  import java.io.BufferedInputStream;
26  import java.io.ByteArrayInputStream;
27  import java.io.ByteArrayOutputStream;
28  import java.io.IOException;
29  import java.io.InputStream;
30  import java.io.InputStreamReader;
31  import java.io.OutputStream;
32  import java.io.OutputStreamWriter;
33  import java.io.Reader;
34  import java.io.StringReader;
35  import java.io.StringWriter;
36  import java.io.Writer;
37  import java.nio.channels.Channel;
38  
39  /**
40   * General IO Stream manipulation.
41   * <p>
42   * This class provides static utility methods for input/output operations, particularly buffered
43   * copying between sources (<code>InputStream</code>, <code>Reader</code>, <code>String</code> and
44   * <code>byte[]</code>) and destinations (<code>OutputStream</code>, <code>Writer</code>,
45   * <code>String</code> and <code>byte[]</code>).
46   * </p>
47   * <p/>
48   * <p>Unless otherwise noted, these <code>copy</code> methods do <em>not</em> flush or close the
49   * streams. Often, doing so would require making non-portable assumptions about the streams' origin
50   * and further use. This means that both streams' <code>close()</code> methods must be called after
51   * copying. if one omits this step, then the stream resources (sockets, file descriptors) are
52   * released when the associated Stream is garbage-collected. It is not a good idea to rely on this
53   * mechanism. For a good overview of the distinction between "memory management" and "resource
54   * management", see <a href="http://www.unixreview.com/articles/1998/9804/9804ja/ja.htm">this
55   * UnixReview article</a></p>
56   * <p/>
57   * <p>For each <code>copy</code> method, a variant is provided that allows the caller to specify the
58   * buffer size (the default is 4k). As the buffer size can have a fairly large impact on speed, this
59   * may be worth tweaking. Often "large buffer -&gt; faster" does not hold, even for large data
60   * transfers.</p>
61   * <p/>
62   * <p>For byte-to-char methods, a <code>copy</code> variant allows the encoding to be selected
63   * (otherwise the platform default is used).</p>
64   * <p/>
65   * <p>The <code>copy</code> methods use an internal buffer when copying. It is therefore advisable
66   * <em>not</em> to deliberately wrap the stream arguments to the <code>copy</code> methods in
67   * <code>Buffered*</code> streams. For example, don't do the
68   * following:</p>
69   * <p/>
70   * <code>copy( new BufferedInputStream( in ), new BufferedOutputStream( out ) );</code>
71   * <p/>
72   * <p>The rationale is as follows:</p>
73   * <p/>
74   * <p>Imagine that an InputStream's read() is a very expensive operation, which would usually suggest
75   * wrapping in a BufferedInputStream. The BufferedInputStream works by issuing infrequent
76   * {@link java.io.InputStream#read(byte[] b, int off, int len)} requests on the underlying InputStream, to
77   * fill an internal buffer, from which further <code>read</code> requests can inexpensively get
78   * their data (until the buffer runs out).</p>
79   * <p>However, the <code>copy</code> methods do the same thing, keeping an internal buffer,
80   * populated by {@link InputStream#read(byte[] b, int off, int len)} requests. Having two buffers
81   * (or three if the destination stream is also buffered) is pointless, and the unnecessary buffer
82   * management hurts performance slightly (about 3%, according to some simple experiments).</p>
83   *
84   * @author <a href="mailto:peter@apache.org">Peter Donald</a>
85   * @author <a href="mailto:jefft@apache.org">Jeff Turner</a>
86   * @version CVS $Revision: 1706718 $ $Date: 2015-10-04 21:37:01 +0200 (Sun, 04 Oct 2015) $
87   * 
88   */
89  public final class IOUtil
90  /*
91   * Behold, intrepid explorers; a map of this class:
92   *
93   *       Method      Input               Output          Dependency
94   *       ------      -----               ------          -------
95   * 1     copy        InputStream         OutputStream    (primitive)
96   * 2     copy        Reader              Writer          (primitive)
97   *
98   * 3     copy        InputStream         Writer          2
99   * 4     toString    InputStream         String          3
100  * 5     toByteArray InputStream         byte[]          1
101  *
102  * 6     copy        Reader              OutputStream    2
103  * 7     toString    Reader              String          2
104  * 8     toByteArray Reader              byte[]          6
105  *
106  * 9     copy        String              OutputStream    2
107  * 10    copy        String              Writer          (trivial)
108  * 11    toByteArray String              byte[]          9
109  *
110  * 12    copy        byte[]              Writer          3
111  * 13    toString    byte[]              String          12
112  * 14    copy        byte[]              OutputStream    (trivial)
113  *
114  *
115  * Note that only the first two methods shuffle bytes; the rest use these two, or (if possible) copy
116  * using native Java copy methods. As there are method variants to specify buffer size and encoding,
117  * each row may correspond to up to 4 methods.
118  *
119  */
120 {
121     private static final int DEFAULT_BUFFER_SIZE = 1024 * 4;
122 
123     /**
124      * Private constructor to prevent instantiation.
125      */
126     private IOUtil()
127     {
128     }
129 
130     ///////////////////////////////////////////////////////////////
131     // Core copy methods
132     ///////////////////////////////////////////////////////////////
133 
134     /**
135      * Copy bytes from an <code>InputStream</code> to an <code>OutputStream</code>.
136      * @param input The input size.
137      * @param output The resulting output.
138      * @throws IOException in case of an error.
139      */
140     public static void copy( @Nonnull final InputStream input, @Nonnull final OutputStream output )
141         throws IOException
142     {
143         copy( input, output, DEFAULT_BUFFER_SIZE );
144     }
145 
146     /**
147      * Copy bytes from an <code>InputStream</code> to an <code>OutputStream</code>.
148      *
149      * @param input The input size.
150      * @param output The resulting output.
151      * @param bufferSize Size of internal buffer to use.
152      * @throws IOException in case of an error.
153      */
154     public static void copy( @Nonnull final InputStream input, @Nonnull final OutputStream output,
155                              final int bufferSize )
156         throws IOException
157     {
158         final byte[] buffer = new byte[bufferSize];
159         int n;
160         while ( -1 != ( n = input.read( buffer ) ) )
161         {
162             output.write( buffer, 0, n );
163         }
164     }
165 
166     /**
167      * Copy chars from a <code>Reader</code> to a <code>Writer</code>.
168      * @param input The input size.
169      * @param output The resulting output.
170      * @throws IOException in case of failure.
171      */
172     public static void copy( @Nonnull final Reader input, @Nonnull final Writer output )
173         throws IOException
174     {
175         copy( input, output, DEFAULT_BUFFER_SIZE );
176     }
177 
178     /**
179      * Copy chars from a <code>Reader</code> to a <code>Writer</code>.
180      *
181      * @param input The input size.
182      * @param output The resulting output.
183      * @param bufferSize Size of internal buffer to use.
184      * @throws IOException in case of failure.
185      */
186     public static void copy( @Nonnull final Reader input, @Nonnull final Writer output, final int bufferSize )
187         throws IOException
188     {
189         final char[] buffer = new char[bufferSize];
190         int n;
191         while ( -1 != ( n = input.read( buffer ) ) )
192         {
193             output.write( buffer, 0, n );
194         }
195         output.flush();
196     }
197 
198     ///////////////////////////////////////////////////////////////
199     // Derived copy methods
200     // InputStream -> *
201     ///////////////////////////////////////////////////////////////
202 
203     ///////////////////////////////////////////////////////////////
204     // InputStream -> Writer
205 
206     /**
207      * Copy and convert bytes from an <code>InputStream</code> to chars on a
208      * <code>Writer</code>.
209      * The platform's default encoding is used for the byte-to-char conversion.
210      * @param input The input size.
211      * @param output The resulting output.
212      * @throws IOException in case of failure.
213      */
214     public static void copy( @Nonnull final InputStream input, @Nonnull final Writer output )
215         throws IOException
216     {
217         copy( input, output, DEFAULT_BUFFER_SIZE );
218     }
219 
220     /**
221      * Copy and convert bytes from an <code>InputStream</code> to chars on a
222      * <code>Writer</code>.
223      * The platform's default encoding is used for the byte-to-char conversion.
224      *
225      * @param input The input size.
226      * @param output The resulting output.
227      * @param bufferSize Size of internal buffer to use.
228      * @throws IOException in case of failure.
229      */
230     public static void copy( @Nonnull final InputStream input, @Nonnull final Writer output, final int bufferSize )
231         throws IOException
232     {
233         final InputStreamReader in = new InputStreamReader( input );
234         copy( in, output, bufferSize );
235     }
236 
237     /**
238      * Copy and convert bytes from an <code>InputStream</code> to chars on a
239      * <code>Writer</code>, using the specified encoding.
240      *
241      * @param input The input size.
242      * @param output The resulting output.
243      * @param encoding The name of a supported character encoding. See the
244      *                 <a href="http://www.iana.org/assignments/character-sets">IANA
245      *                 Charset Registry</a> for a list of valid encoding types.
246      * @throws IOException in case of failure.
247      */
248     public static void copy( @Nonnull final InputStream input, @Nonnull final Writer output,
249                              @Nonnull final String encoding )
250         throws IOException
251     {
252         final InputStreamReader in = new InputStreamReader( input, encoding );
253         copy( in, output );
254     }
255 
256     /**
257      * Copy and convert bytes from an <code>InputStream</code> to chars on a
258      * <code>Writer</code>, using the specified encoding.
259      *
260      * @param encoding   The name of a supported character encoding. See the
261      *                   <a href="http://www.iana.org/assignments/character-sets">IANA
262      *                   Charset Registry</a> for a list of valid encoding types.
263      * @param input The input size.
264      * @param output The resulting output.
265      * @param bufferSize Size of internal buffer to use.
266      * @throws IOException in case of failure.
267      */
268     public static void copy( @Nonnull final InputStream input, @Nonnull final Writer output,
269                              @Nonnull final String encoding, final int bufferSize )
270         throws IOException
271     {
272         final InputStreamReader in = new InputStreamReader( input, encoding );
273         copy( in, output, bufferSize );
274     }
275 
276     ///////////////////////////////////////////////////////////////
277     // InputStream -> String
278 
279     /**
280      * Get the contents of an <code>InputStream</code> as a String.
281      * The platform's default encoding is used for the byte-to-char conversion.
282      * @param input The input size.
283      * @return The resulting string.
284      * @throws IOException in case of failure.
285      */
286     @Nonnull public static String toString( @Nonnull final InputStream input )
287         throws IOException
288     {
289         return toString( input, DEFAULT_BUFFER_SIZE );
290     }
291 
292     /**
293      * Get the contents of an <code>InputStream</code> as a String.
294      * The platform's default encoding is used for the byte-to-char conversion.
295      *
296      * @param input The input size.
297      * @param bufferSize Size of internal buffer to use.
298      * @return the resulting string.
299      * @throws IOException in case of failure.
300      */
301     @Nonnull public static String toString( @Nonnull final InputStream input, final int bufferSize )
302         throws IOException
303     {
304         final StringWriter sw = new StringWriter();
305         copy( input, sw, bufferSize );
306         return sw.toString();
307     }
308 
309     /**
310      * Get the contents of an <code>InputStream</code> as a String.
311      *
312      * @param input The input size.
313      * @param encoding The name of a supported character encoding. See the
314      *                 <a href="http://www.iana.org/assignments/character-sets">IANA
315      *                 Charset Registry</a> for a list of valid encoding types.
316      * @return the converted string.
317      * @throws IOException in case of failure.
318      */
319     @Nonnull public static String toString( @Nonnull final InputStream input, @Nonnull final String encoding )
320         throws IOException
321     {
322         return toString( input, encoding, DEFAULT_BUFFER_SIZE );
323     }
324 
325     /**
326      * Get the contents of an <code>InputStream</code> as a String.
327      *
328      * @param input The input size.
329      * @param encoding   The name of a supported character encoding. See the
330      *                   <a href="http://www.iana.org/assignments/character-sets">IANA
331      *                   Charset Registry</a> for a list of valid encoding types.
332      * @param bufferSize Size of internal buffer to use.
333      * @return The converted string.
334      * @throws IOException in case of failure.
335      */
336     @Nonnull public static String toString( @Nonnull final InputStream input, @Nonnull final String encoding,
337                                             final int bufferSize )
338         throws IOException
339     {
340         final StringWriter sw = new StringWriter();
341         copy( input, sw, encoding, bufferSize );
342         return sw.toString();
343     }
344 
345     ///////////////////////////////////////////////////////////////
346     // InputStream -> byte[]
347 
348     /**
349      * Get the contents of an <code>InputStream</code> as a <code>byte[]</code>.
350      * @param input The input size.
351      * @return the resulting byte array.
352      * @throws IOException in case of failure.
353      */
354     @Nonnull public static byte[] toByteArray( @Nonnull final InputStream input )
355         throws IOException
356     {
357         return toByteArray( input, DEFAULT_BUFFER_SIZE );
358     }
359 
360     /**
361      * Get the contents of an <code>InputStream</code> as a <code>byte[]</code>.
362      *
363      * @param input The input size.
364      * @param bufferSize Size of internal buffer to use.
365      * @return the resulting byte array.
366      * @throws IOException in case of failure.
367      */
368     @Nonnull public static byte[] toByteArray( @Nonnull final InputStream input, final int bufferSize )
369         throws IOException
370     {
371         final ByteArrayOutputStream output = new ByteArrayOutputStream();
372         copy( input, output, bufferSize );
373         return output.toByteArray();
374     }
375 
376     ///////////////////////////////////////////////////////////////
377     // Derived copy methods
378     // Reader -> *
379     ///////////////////////////////////////////////////////////////
380 
381     ///////////////////////////////////////////////////////////////
382     // Reader -> OutputStream
383 
384     /**
385      * Serialize chars from a <code>Reader</code> to bytes on an <code>OutputStream</code>, and
386      * flush the <code>OutputStream</code>.
387      * @param input The input size.
388      * @param output The resulting output.
389      * @throws IOException in case of failure.
390      */
391     public static void copy( @Nonnull final Reader input, @Nonnull final OutputStream output )
392         throws IOException
393     {
394         copy( input, output, DEFAULT_BUFFER_SIZE );
395     }
396 
397     /**
398      * Serialize chars from a <code>Reader</code> to bytes on an <code>OutputStream</code>, and
399      * flush the <code>OutputStream</code>.
400      *
401      * @param input The input size.
402      * @param output The resulting output.
403      * @param bufferSize Size of internal buffer to use.
404      * @throws IOException in case of failure.
405      */
406     public static void copy( @Nonnull final Reader input, @Nonnull final OutputStream output, final int bufferSize )
407         throws IOException
408     {
409         final OutputStreamWriter out = new OutputStreamWriter( output );
410         copy( input, out, bufferSize );
411         // NOTE: Unless anyone is planning on rewriting OutputStreamWriter, we have to flush
412         // here.
413         out.flush();
414     }
415 
416     ///////////////////////////////////////////////////////////////
417     // Reader -> String
418 
419     /**
420      * Get the contents of a <code>Reader</code> as a String.
421      * @param input The input size.
422      * @return The converted string.
423      * @throws IOException in case of failure.
424      */
425     @Nonnull public static String toString( @Nonnull final Reader input )
426         throws IOException
427     {
428         return toString( input, DEFAULT_BUFFER_SIZE );
429     }
430 
431     /**
432      * Get the contents of a <code>Reader</code> as a String.
433      *
434      * @param input The input size.
435      * @param bufferSize Size of internal buffer to use.
436      * @return the resulting byte array.
437      * @throws IOException in case of failure.
438      */
439     @Nonnull public static String toString( @Nonnull final Reader input, final int bufferSize )
440         throws IOException
441     {
442         final StringWriter sw = new StringWriter();
443         copy( input, sw, bufferSize );
444         return sw.toString();
445     }
446 
447     ///////////////////////////////////////////////////////////////
448     // Reader -> byte[]
449 
450     /**
451      * Get the contents of a <code>Reader</code> as a <code>byte[]</code>.
452      * @param input The input size.
453      * @return the resulting byte array.
454      * @throws IOException in case of failure.
455      */
456     @Nonnull public static byte[] toByteArray( @Nonnull final Reader input )
457         throws IOException
458     {
459         return toByteArray( input, DEFAULT_BUFFER_SIZE );
460     }
461 
462     /**
463      * Get the contents of a <code>Reader</code> as a <code>byte[]</code>.
464      *
465      * @param input The input size.
466      * @param bufferSize Size of internal buffer to use.
467      * @return the resulting byte array.
468      * @throws IOException in case of failure.
469      */
470     @Nonnull public static byte[] toByteArray( @Nonnull final Reader input, final int bufferSize )
471         throws IOException
472     {
473         ByteArrayOutputStream output = new ByteArrayOutputStream();
474         copy( input, output, bufferSize );
475         return output.toByteArray();
476     }
477 
478     ///////////////////////////////////////////////////////////////
479     // Derived copy methods
480     // String -> *
481     ///////////////////////////////////////////////////////////////
482 
483     ///////////////////////////////////////////////////////////////
484     // String -> OutputStream
485 
486     /**
487      * Serialize chars from a <code>String</code> to bytes on an <code>OutputStream</code>, and
488      * flush the <code>OutputStream</code>.
489      * @param input The input size.
490      * @param output The resulting output.
491      * @throws IOException in case of failure.
492      */
493     public static void copy( @Nonnull final String input, @Nonnull final OutputStream output )
494         throws IOException
495     {
496         copy( input, output, DEFAULT_BUFFER_SIZE );
497     }
498 
499     /**
500      * Serialize chars from a <code>String</code> to bytes on an <code>OutputStream</code>, and
501      * flush the <code>OutputStream</code>.
502      *
503      * @param input The input size.
504      * @param output The resulting output.
505      * @param bufferSize Size of internal buffer to use.
506      * @throws IOException in case of failure.
507      */
508     public static void copy( @Nonnull final String input, @Nonnull final OutputStream output, final int bufferSize )
509         throws IOException
510     {
511         final StringReader in = new StringReader( input );
512         final OutputStreamWriter out = new OutputStreamWriter( output );
513         copy( in, out, bufferSize );
514         // NOTE: Unless anyone is planning on rewriting OutputStreamWriter, we have to flush
515         // here.
516         out.flush();
517     }
518 
519     ///////////////////////////////////////////////////////////////
520     // String -> Writer
521 
522     /**
523      * Copy chars from a <code>String</code> to a <code>Writer</code>.
524      * @param input Input string.
525      * @param output resulting output {@link Writer}
526      * @throws IOException in case of failure.
527      */
528     public static void copy( @Nonnull final String input, @Nonnull final Writer output )
529         throws IOException
530     {
531         output.write( input );
532     }
533 
534     ///////////////////////////////////////////////////////////////
535     // String -> byte[]
536 
537     /**
538      * Get the contents of a <code>String</code> as a <code>byte[]</code>.
539      * @param input The input size.
540      * @return The resulting byte array.
541      * @throws IOException in case of failure.
542      */
543     @Nonnull public static byte[] toByteArray( @Nonnull final String input )
544         throws IOException
545     {
546         return toByteArray( input, DEFAULT_BUFFER_SIZE );
547     }
548 
549     /**
550      * Get the contents of a <code>String</code> as a <code>byte[]</code>.
551      *
552      * @param input The input size.
553      * @param bufferSize Size of internal buffer to use.
554      * @return The resulting byte array.
555      * @throws IOException in case of failure.
556      */
557     @Nonnull public static byte[] toByteArray( @Nonnull final String input, final int bufferSize )
558         throws IOException
559     {
560         ByteArrayOutputStream output = new ByteArrayOutputStream();
561         copy( input, output, bufferSize );
562         return output.toByteArray();
563     }
564 
565     ///////////////////////////////////////////////////////////////
566     // Derived copy methods
567     // byte[] -> *
568     ///////////////////////////////////////////////////////////////
569 
570     ///////////////////////////////////////////////////////////////
571     // byte[] -> Writer
572 
573     /**
574      * Copy and convert bytes from a <code>byte[]</code> to chars on a
575      * <code>Writer</code>.
576      * The platform's default encoding is used for the byte-to-char conversion.
577      * @param input The input size.
578      * @param output The resulting output.
579      * @throws IOException in case of failure.
580      */
581     public static void copy( @Nonnull final byte[] input, @Nonnull final Writer output )
582         throws IOException
583     {
584         copy( input, output, DEFAULT_BUFFER_SIZE );
585     }
586 
587     /**
588      * Copy and convert bytes from a <code>byte[]</code> to chars on a
589      * <code>Writer</code>.
590      * The platform's default encoding is used for the byte-to-char conversion.
591      *
592      * @param input The input size.
593      * @param output The resulting output.
594      * @param bufferSize Size of internal buffer to use.
595      * @throws IOException in case of failure.
596      */
597     public static void copy( @Nonnull final byte[] input, @Nonnull final Writer output, final int bufferSize )
598         throws IOException
599     {
600         final ByteArrayInputStream in = new ByteArrayInputStream( input );
601         copy( in, output, bufferSize );
602     }
603 
604     /**
605      * Copy and convert bytes from a <code>byte[]</code> to chars on a
606      * <code>Writer</code>, using the specified encoding.
607      *
608      * @param encoding The name of a supported character encoding. See the
609      *                 <a href="http://www.iana.org/assignments/character-sets">IANA
610      *                 Charset Registry</a> for a list of valid encoding types.
611      * @param input The input size.
612      * @param output The resulting output.
613      * @throws IOException in case of failure.
614      */
615     public static void copy( @Nonnull final byte[] input, @Nonnull final Writer output, final String encoding )
616         throws IOException
617     {
618         final ByteArrayInputStream in = new ByteArrayInputStream( input );
619         copy( in, output, encoding );
620     }
621 
622     /**
623      * Copy and convert bytes from a <code>byte[]</code> to chars on a
624      * <code>Writer</code>, using the specified encoding.
625      *
626      * @param encoding   The name of a supported character encoding. See the
627      *                   <a href="http://www.iana.org/assignments/character-sets">IANA
628      *                   Charset Registry</a> for a list of valid encoding types.
629      * @param input The input bytes.
630      * @param output The output buffer {@link Writer}
631      * @param bufferSize Size of internal buffer to use.
632      * @throws IOException in case of failure.
633      */
634     public static void copy( @Nonnull final byte[] input, @Nonnull final Writer output, @Nonnull final String encoding,
635                              final int bufferSize )
636         throws IOException
637     {
638         final ByteArrayInputStream in = new ByteArrayInputStream( input );
639         copy( in, output, encoding, bufferSize );
640     }
641 
642     ///////////////////////////////////////////////////////////////
643     // byte[] -> String
644 
645     /**
646      * Get the contents of a <code>byte[]</code> as a String.
647      * The platform's default encoding is used for the byte-to-char conversion.
648      * @param input The input bytes.
649      * @return The resulting string.
650      * @throws IOException in case of failure.
651      */
652     @Nonnull public static String toString( @Nonnull final byte[] input )
653         throws IOException
654     {
655         return toString( input, DEFAULT_BUFFER_SIZE );
656     }
657 
658     /**
659      * Get the contents of a <code>byte[]</code> as a String.
660      * The platform's default encoding is used for the byte-to-char conversion.
661      *
662      * @param bufferSize Size of internal buffer to use.
663      * @param input The input bytes.
664      * @return The created string.
665      * @throws IOException in case of failure.
666      */
667     @Nonnull public static String toString( @Nonnull final byte[] input, final int bufferSize )
668         throws IOException
669     {
670         final StringWriter sw = new StringWriter();
671         copy( input, sw, bufferSize );
672         return sw.toString();
673     }
674 
675     /**
676      * Get the contents of a <code>byte[]</code> as a String.
677      *
678      * @param encoding The name of a supported character encoding. See the
679      *                 <a href="http://www.iana.org/assignments/character-sets">IANA
680      *                 Charset Registry</a> for a list of valid encoding types.
681      * @param input The input bytes.
682      * @return The resulting string.
683      * @throws IOException in case of failure.
684      */
685     @Nonnull public static String toString( @Nonnull final byte[] input, @Nonnull final String encoding )
686         throws IOException
687     {
688         return toString( input, encoding, DEFAULT_BUFFER_SIZE );
689     }
690 
691     /**
692      * Get the contents of a <code>byte[]</code> as a String.
693      *
694      * @param encoding   The name of a supported character encoding. See the
695      *                   <a href="http://www.iana.org/assignments/character-sets">IANA
696      *                   Charset Registry</a> for a list of valid encoding types.
697      * @param bufferSize Size of internal buffer to use.
698      * @param input Input bytes.
699      * @return The resulting string.
700      * @throws IOException in case of failure.
701      */
702     @Nonnull public static String toString( @Nonnull final byte[] input, @Nonnull final String encoding,
703                                             final int bufferSize )
704         throws IOException
705     {
706         final StringWriter sw = new StringWriter();
707         copy( input, sw, encoding, bufferSize );
708         return sw.toString();
709     }
710 
711     ///////////////////////////////////////////////////////////////
712     // byte[] -> OutputStream
713 
714     /**
715      * Copy bytes from a <code>byte[]</code> to an <code>OutputStream</code>.
716      * @param input Input byte array.
717      * @param output output stream {@link OutputStream}
718      * @throws IOException in case of failure.
719      */
720     public static void copy( @Nonnull final byte[] input, @Nonnull final OutputStream output )
721         throws IOException
722     {
723         output.write( input );
724     }
725 
726     /**
727      * Compare the contents of two Streams to determine if they are equal or not.
728      *
729      * @param input1 the first stream
730      * @param input2 the second stream
731      * @return true if the content of the streams are equal or they both don't exist, false otherwise
732      * @throws IOException in case of failure.
733      */
734     public static boolean contentEquals( @Nonnull final InputStream input1, @Nonnull final InputStream input2 )
735         throws IOException
736     {
737         final InputStream bufferedInput1 = new BufferedInputStream( input1 );
738         final InputStream bufferedInput2 = new BufferedInputStream( input2 );
739 
740         int ch = bufferedInput1.read();
741         while ( -1 != ch )
742         {
743             final int ch2 = bufferedInput2.read();
744             if ( ch != ch2 )
745             {
746                 return false;
747             }
748             ch = bufferedInput1.read();
749         }
750 
751         final int ch2 = bufferedInput2.read();
752         return -1 == ch2;
753     }
754 
755     // ----------------------------------------------------------------------
756     // closeXXX()
757     // ----------------------------------------------------------------------
758 
759     /**
760      * Closes a channel. Channel can be null and any IOException's will be swallowed.
761      *
762      * @param channel The stream to close.
763      */
764     public static void close( @Nullable Channel channel )
765     {
766         if ( channel == null )
767         {
768             return;
769         }
770 
771         try
772         {
773             channel.close();
774         }
775         catch ( IOException ex )
776         {
777             // ignore
778         }
779     }
780 
781     /**
782      * Closes the input stream. The input stream can be null and any IOException's will be swallowed.
783      *
784      * @param inputStream The stream to close.
785      */
786     public static void close( @Nullable InputStream inputStream )
787     {
788         if ( inputStream == null )
789         {
790             return;
791         }
792 
793         try
794         {
795             inputStream.close();
796         }
797         catch ( IOException ex )
798         {
799             // ignore
800         }
801     }
802 
803     /**
804      * Closes the output stream. The output stream can be null and any IOException's will be swallowed.
805      *
806      * @param outputStream The stream to close.
807      */
808     public static void close( @Nullable OutputStream outputStream )
809     {
810         if ( outputStream == null )
811         {
812             return;
813         }
814 
815         try
816         {
817             outputStream.close();
818         }
819         catch ( IOException ex )
820         {
821             // ignore
822         }
823     }
824 
825     /**
826      * Closes the reader. The reader can be null and any IOException's will be swallowed.
827      *
828      * @param reader The reader to close.
829      */
830     public static void close( @Nullable Reader reader )
831     {
832         if ( reader == null )
833         {
834             return;
835         }
836 
837         try
838         {
839             reader.close();
840         }
841         catch ( IOException ex )
842         {
843             // ignore
844         }
845     }
846 
847     /**
848      * Closes the writer. The writer can be null and any IOException's will be swallowed.
849      *
850      * @param writer The writer to close.
851      */
852     public static void close( @Nullable Writer writer )
853     {
854         if ( writer == null )
855         {
856             return;
857         }
858 
859         try
860         {
861             writer.close();
862         }
863         catch ( IOException ex )
864         {
865             // ignore
866         }
867     }
868 }