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   * 
47   * <p>Unless otherwise noted, these <code>copy</code> methods do <em>not</em> flush or close the
48   * streams. Often, doing so would require making non-portable assumptions about the streams' origin
49   * and further use. This means that both streams' <code>close()</code> methods must be called after
50   * copying. if one omits this step, then the stream resources (sockets, file descriptors) are
51   * released when the associated Stream is garbage-collected. It is not a good idea to rely on this
52   * mechanism.</p>
53   * 
54   * <p>For each <code>copy</code> method, a variant is provided that allows the caller to specify the
55   * buffer size (the default is 4k). As the buffer size can have a fairly large impact on speed, this
56   * may be worth tweaking. Often "large buffer -&gt; faster" does not hold, even for large data
57   * transfers.</p>
58   * <p>For byte-to-char methods, a <code>copy</code> variant allows the encoding to be selected
59   * (otherwise the platform default is used).</p>
60   * <p>The <code>copy</code> methods use an internal buffer when copying. It is therefore advisable
61   * <em>not</em> to deliberately wrap the stream arguments to the <code>copy</code> methods in
62   * <code>Buffered*</code> streams. For example, don't do the
63   * following:</p>
64   * <p>
65   * <code>copy( new BufferedInputStream( in ), new BufferedOutputStream( out ) );</code>
66   * </p>
67   * <p>The rationale is as follows:</p>
68   * 
69   * <p>Imagine that an InputStream's read() is a very expensive operation, which would usually suggest
70   * wrapping in a BufferedInputStream. The BufferedInputStream works by issuing infrequent
71   * {@link java.io.InputStream#read(byte[] b, int off, int len)} requests on the underlying InputStream, to
72   * fill an internal buffer, from which further <code>read</code> requests can inexpensively get
73   * their data (until the buffer runs out).</p>
74   * <p>However, the <code>copy</code> methods do the same thing, keeping an internal buffer,
75   * populated by {@link InputStream#read(byte[] b, int off, int len)} requests. Having two buffers
76   * (or three if the destination stream is also buffered) is pointless, and the unnecessary buffer
77   * management hurts performance slightly (about 3%, according to some simple experiments).</p>
78   *
79   * @author <a href="mailto:peter@apache.org">Peter Donald</a>
80   * @author <a href="mailto:jefft@apache.org">Jeff Turner</a>
81   * @version CVS $Revision$ $Date$
82   *
83   */
84  public final class IOUtil
85  /*
86   * Behold, intrepid explorers; a map of this class:
87   *
88   *       Method      Input               Output          Dependency
89   *       ------      -----               ------          -------
90   * 1     copy        InputStream         OutputStream    (primitive)
91   * 2     copy        Reader              Writer          (primitive)
92   *
93   * 3     copy        InputStream         Writer          2
94   * 4     toString    InputStream         String          3
95   * 5     toByteArray InputStream         byte[]          1
96   *
97   * 6     copy        Reader              OutputStream    2
98   * 7     toString    Reader              String          2
99   * 8     toByteArray Reader              byte[]          6
100  *
101  * 9     copy        String              OutputStream    2
102  * 10    copy        String              Writer          (trivial)
103  * 11    toByteArray String              byte[]          9
104  *
105  * 12    copy        byte[]              Writer          3
106  * 13    toString    byte[]              String          12
107  * 14    copy        byte[]              OutputStream    (trivial)
108  *
109  *
110  * Note that only the first two methods shuffle bytes; the rest use these two, or (if possible) copy
111  * using native Java copy methods. As there are method variants to specify buffer size and encoding,
112  * each row may correspond to up to 4 methods.
113  *
114  */
115 {
116     private static final int DEFAULT_BUFFER_SIZE = 1024 * 4;
117 
118     /**
119      * Private constructor to prevent instantiation.
120      */
121     private IOUtil()
122     {
123     }
124 
125     ///////////////////////////////////////////////////////////////
126     // Core copy methods
127     ///////////////////////////////////////////////////////////////
128 
129     /**
130      * Copy bytes from an <code>InputStream</code> to an <code>OutputStream</code>.
131      * 
132      * @param input the stream to read from
133      * @param output the stream to write to
134      * @throws IOException in case of an error
135      * @deprecated use {@code org.apache.commons.io.IOUtils.copy()} or in
136      *         Java 9 and later {@code InputStream.transferTo()}.
137      */
138     @Deprecated
139     public static void copy( @Nonnull final InputStream input, @Nonnull final OutputStream output )
140         throws IOException
141     {
142         copy( input, output, DEFAULT_BUFFER_SIZE );
143     }
144 
145     /**
146      * Copy bytes from an <code>InputStream</code> to an <code>OutputStream</code>.
147      *
148      * In Java 9 and later this is replaced by {@code InputStream.transferTo()}.
149      * 
150      * @param input the stream to read from
151      * @param output the stream to write to
152      * @param bufferSize size of internal buffer
153      * @throws IOException in case of an error
154      * @deprecated use {@code org.apache.commons.io.IOUtils.copy()} or in
155      *         Java 9 and later {@code InputStream.transferTo()}.
156      */
157     @Deprecated
158     public static void copy( @Nonnull final InputStream input, @Nonnull final OutputStream output,
159                              final int bufferSize )
160         throws IOException
161     {
162         final byte[] buffer = new byte[bufferSize];
163         int n;
164         while ( -1 != ( n = input.read( buffer ) ) )
165         {
166             output.write( buffer, 0, n );
167         }
168     }
169 
170     /**
171      * Copy chars from a <code>Reader</code> to a <code>Writer</code>.
172      * 
173      * @param input the reader to read from
174      * @param output the writer to write to
175      * @throws IOException in case of failure     * @deprecated use {@code org.apache.commons.io.IOUtils.copy()}.
176      */
177     @Deprecated
178     public static void copy( @Nonnull final Reader input, @Nonnull final Writer output )
179         throws IOException
180     {
181         copy( input, output, DEFAULT_BUFFER_SIZE );
182     }
183 
184     /**
185      * Copy chars from a <code>Reader</code> to a <code>Writer</code>.
186      *
187      * @param input the reader to read from
188      * @param output the writer to write to
189      * @param bufferSize size of internal buffer
190      * @throws IOException in case of failure
191      * @deprecated use {@code org.apache.commons.io.IOUtils.copy()}.
192      */
193     @Deprecated
194     public static void copy( @Nonnull final Reader input, @Nonnull final Writer output, final int bufferSize )
195         throws IOException
196     {
197         final char[] buffer = new char[bufferSize];
198         int n;
199         while ( -1 != ( n = input.read( buffer ) ) )
200         {
201             output.write( buffer, 0, n );
202         }
203         output.flush();
204     }
205 
206     ///////////////////////////////////////////////////////////////
207     // Derived copy methods
208     // InputStream -> *
209     ///////////////////////////////////////////////////////////////
210 
211     ///////////////////////////////////////////////////////////////
212     // InputStream -> Writer
213 
214     /**
215      * Copy and convert bytes from an <code>InputStream</code> to chars on a
216      * <code>Writer</code>.
217      * 
218      * The platform's default encoding is used for the byte-to-char conversion.
219      * 
220      * @param input the reader to read from
221      * @param output the writer to write to
222      * @throws IOException in case of failure
223      * @deprecated use {@code org.apache.commons.io.IOUtils.copy()}.
224      */
225     @Deprecated
226     public static void copy( @Nonnull final InputStream input, @Nonnull final Writer output )
227         throws IOException
228     {
229         copy( input, output, DEFAULT_BUFFER_SIZE );
230     }
231 
232     /**
233      * Copy and convert bytes from an <code>InputStream</code> to chars on a
234      * <code>Writer</code>.
235      * The platform's default encoding is used for the byte-to-char conversion.
236      *
237      * @param input the input stream to read from
238      * @param output the writer to write to
239      * @param bufferSize size of internal buffer
240      * @throws IOException in case of failure
241      * @deprecated use {@code org.apache.commons.io.IOUtils.copy()}.
242      */
243     @Deprecated
244     public static void copy( @Nonnull final InputStream input, @Nonnull final Writer output, final int bufferSize )
245         throws IOException
246     {
247         final InputStreamReader in = new InputStreamReader( input );
248         copy( in, output, bufferSize );
249     }
250 
251     /**
252      * Copy and convert bytes from an <code>InputStream</code> to chars on a
253      * <code>Writer</code>, using the specified encoding.
254      *
255      * @param input the input stream to read from
256      * @param output the writer to write to
257      * @param encoding the name of a supported character encoding. See the
258      *                 <a href="https://www.iana.org/assignments/character-sets">IANA
259      *                 Charset Registry</a> for a list of valid encoding types.
260      * @throws IOException in case of failure
261      * @deprecated use {@code org.apache.commons.io.IOUtils.copy()}.
262      */
263     @Deprecated
264     public static void copy( @Nonnull final InputStream input, @Nonnull final Writer output,
265                              @Nonnull final String encoding )
266         throws IOException
267     {
268         final InputStreamReader in = new InputStreamReader( input, encoding );
269         copy( in, output );
270     }
271 
272     /**
273      * Copy and convert bytes from an <code>InputStream</code> to chars on a
274      * <code>Writer</code>, using the specified encoding.
275      *
276      * @param encoding   the name of a supported character encoding. See the
277      *                   <a href="https://www.iana.org/assignments/character-sets">IANA
278      *                   Charset Registry</a> for a list of valid encoding types.
279      * @param input the input stream to read from
280      * @param output the writer to write to
281      * @param bufferSize size of internal buffer
282      * @throws IOException in case of failure
283      * @deprecated use {@code org.apache.commons.io.IOUtils.copy()}.
284      */
285     @Deprecated
286     public static void copy( @Nonnull final InputStream input, @Nonnull final Writer output,
287                              @Nonnull final String encoding, final int bufferSize )
288         throws IOException
289     {
290         final InputStreamReader in = new InputStreamReader( input, encoding );
291         copy( in, output, bufferSize );
292     }
293 
294     ///////////////////////////////////////////////////////////////
295     // InputStream -> String
296 
297     /**
298      * Get the contents of an <code>InputStream</code> as a String.
299      * The platform's default encoding is used for the byte-to-char conversion.
300      * 
301      * @param input the InputStream to read from
302      * @return the resulting string
303      * @throws IOException in case of failure
304      * @deprecated always specify a character encoding
305      */
306     @Deprecated
307     @Nonnull public static String toString( @Nonnull final InputStream input )
308         throws IOException
309     {
310         return toString( input, DEFAULT_BUFFER_SIZE );
311     }
312 
313     /**
314      * Get the contents of an <code>InputStream</code> as a String.
315      * The platform's default encoding is used for the byte-to-char conversion.
316      *
317      * @param input the InputStream to read from
318      * @param bufferSize size of internal buffer
319      * @return the resulting string
320      * @throws IOException in case of failure
321      * @deprecated always specify a character encoding
322      */
323     @Deprecated
324     @Nonnull public static String toString( @Nonnull final InputStream input, final int bufferSize )
325         throws IOException
326     {
327         final StringWriter sw = new StringWriter();
328         copy( input, sw, bufferSize );
329         return sw.toString();
330     }
331 
332     /**
333      * Get the contents of an <code>InputStream</code> as a String.
334      *
335      * @param input the InputStream to read from
336      * @param encoding the name of a supported character encoding. See the
337      *                 <a href="https://www.iana.org/assignments/character-sets">IANA
338      *                 Charset Registry</a> for a list of valid encoding types.
339      * @return the converted string
340      * @throws IOException in case of failure
341      * @deprecated use {@code org.apache.commons.io.IOUtils.toString()}.
342      */
343     @Deprecated
344     @Nonnull public static String toString( @Nonnull final InputStream input, @Nonnull final String encoding )
345         throws IOException
346     {
347         return toString( input, encoding, DEFAULT_BUFFER_SIZE );
348     }
349 
350     /**
351      * Get the contents of an <code>InputStream</code> as a String.
352      *
353      * @param input the InputStream to read from
354      * @param encoding   the name of a supported character encoding. See the
355      *                   <a href="https://www.iana.org/assignments/character-sets">IANA
356      *                   Charset Registry</a> for a list of valid encoding types.
357      * @param bufferSize size of internal buffer
358      * @return The converted string.
359      * @throws IOException in case of failure
360      * @deprecated use {@code org.apache.commons.io.IOUtils.toString()}.
361      */
362     @Deprecated
363     @Nonnull public static String toString( @Nonnull final InputStream input, @Nonnull final String encoding,
364                                             final int bufferSize )
365         throws IOException
366     {
367         final StringWriter sw = new StringWriter();
368         copy( input, sw, encoding, bufferSize );
369         return sw.toString();
370     }
371 
372     ///////////////////////////////////////////////////////////////
373     // InputStream -> byte[]
374 
375     /**
376      * Get the contents of an <code>InputStream</code> as a <code>byte[]</code>.
377      * 
378      * @param input the InputStream to read from
379      * @return the resulting byte array.
380      * @throws IOException in case of failure
381      * @deprecated use {@code org.apache.commons.io.IOUtils.readFully()}.
382      */
383     @Deprecated
384     @Nonnull public static byte[] toByteArray( @Nonnull final InputStream input )
385         throws IOException
386     {
387         return toByteArray( input, DEFAULT_BUFFER_SIZE );
388     }
389 
390     /**
391      * Get the contents of an <code>InputStream</code> as a <code>byte[]</code>.
392      *
393      * @param input the InputStream to read from
394      * @param bufferSize size of internal buffer
395      * @return the resulting byte array.
396      * @throws IOException in case of failure
397      * @deprecated use {@code org.apache.commons.io.IOUtils.readFully()}.
398      */
399     @Deprecated
400     @Nonnull public static byte[] toByteArray( @Nonnull final InputStream input, final int bufferSize )
401         throws IOException
402     {
403         final ByteArrayOutputStream output = new ByteArrayOutputStream();
404         copy( input, output, bufferSize );
405         return output.toByteArray();
406     }
407 
408     ///////////////////////////////////////////////////////////////
409     // Derived copy methods
410     // Reader -> *
411     ///////////////////////////////////////////////////////////////
412 
413     ///////////////////////////////////////////////////////////////
414     // Reader -> OutputStream
415 
416     /**
417      * Serialize chars from a <code>Reader</code> to bytes on an <code>OutputStream</code>, and
418      * flush the <code>OutputStream</code>.
419      * 
420      * @param input the InputStream to read from
421      * @param output the output stream to write to
422      * @throws IOException in case of failure
423      * @deprecated always specify a character encoding
424      */
425     @Deprecated
426     public static void copy( @Nonnull final Reader input, @Nonnull final OutputStream output )
427         throws IOException
428     {
429         copy( input, output, DEFAULT_BUFFER_SIZE );
430     }
431 
432     /**
433      * Serialize chars from a <code>Reader</code> to bytes on an <code>OutputStream</code>, and
434      * flush the <code>OutputStream</code>.
435      *
436      * @param input the InputStream to read from
437      * @param output the output to write to
438      * @param bufferSize size of internal buffer
439      * @throws IOException in case of failure
440      * @deprecated always specify a character encoding
441      */
442     @Deprecated
443     public static void copy( @Nonnull final Reader input, @Nonnull final OutputStream output, final int bufferSize )
444         throws IOException
445     {
446         final OutputStreamWriter out = new OutputStreamWriter( output );
447         copy( input, out, bufferSize );
448         // NOTE: Unless anyone is planning on rewriting OutputStreamWriter, we have to flush
449         // here.
450         out.flush();
451     }
452 
453     ///////////////////////////////////////////////////////////////
454     // Reader -> String
455 
456     /**
457      * Get the contents of a <code>Reader</code> as a String.
458      * @param input the InputStream to read from
459      * @return The converted string.
460      * @throws IOException in case of failure
461      * @deprecated use {@code org.apache.commons.io.IOUtils.toString()}.
462      */
463     @Deprecated
464     @Nonnull public static String toString( @Nonnull final Reader input )
465         throws IOException
466     {
467         return toString( input, DEFAULT_BUFFER_SIZE );
468     }
469 
470     /**
471      * Get the contents of a <code>Reader</code> as a String.
472      *
473      * @param input the reader to read from
474      * @param bufferSize size of internal buffer
475      * @return the resulting byte array.
476      * @throws IOException in case of failure
477      * @deprecated use {@code org.apache.commons.io.IOUtils.toString()}.
478      */
479     @Deprecated
480     @Nonnull public static String toString( @Nonnull final Reader input, final int bufferSize )
481         throws IOException
482     {
483         final StringWriter sw = new StringWriter();
484         copy( input, sw, bufferSize );
485         return sw.toString();
486     }
487 
488     ///////////////////////////////////////////////////////////////
489     // Reader -> byte[]
490 
491     /**
492      * Get the contents of a <code>Reader</code> as a <code>byte[]</code>.
493      * 
494      * @param input the InputStream to read from
495      * @return the resulting byte array.
496      * @throws IOException in case of failure
497      * @deprecated always specify a character encoding
498      */
499     @Deprecated
500     @Nonnull public static byte[] toByteArray( @Nonnull final Reader input )
501         throws IOException
502     {
503         return toByteArray( input, DEFAULT_BUFFER_SIZE );
504     }
505 
506     /**
507      * Get the contents of a <code>Reader</code> as a <code>byte[]</code>.
508      *
509      * @param input the InputStream to read from
510      * @param bufferSize size of internal buffer
511      * @return the resulting byte array.
512      * @throws IOException in case of failure
513      * @deprecated always specify a character encoding
514      */
515     @Deprecated
516     @Nonnull public static byte[] toByteArray( @Nonnull final Reader input, final int bufferSize )
517         throws IOException
518     {
519         ByteArrayOutputStream output = new ByteArrayOutputStream();
520         copy( input, output, bufferSize );
521         return output.toByteArray();
522     }
523 
524     ///////////////////////////////////////////////////////////////
525     // Derived copy methods
526     // String -> *
527     ///////////////////////////////////////////////////////////////
528 
529     ///////////////////////////////////////////////////////////////
530     // String -> OutputStream
531 
532     /**
533      * Serialize chars from a <code>String</code> to bytes on an <code>OutputStream</code>, and
534      * flush the <code>OutputStream</code>.
535      * @param input the InputStream to read from
536      * @param output the output to write to
537      * @throws IOException in case of failure
538      * @deprecated always specify a character encoding
539      */
540     @Deprecated
541     public static void copy( @Nonnull final String input, @Nonnull final OutputStream output )
542         throws IOException
543     {
544         copy( input, output, DEFAULT_BUFFER_SIZE );
545     }
546 
547     /**
548      * Serialize chars from a <code>String</code> to bytes on an <code>OutputStream</code>, and
549      * flush the <code>OutputStream</code>.
550      *
551      * @param input the InputStream to read from
552      * @param output the output to write to
553      * @param bufferSize size of internal buffer
554      * @throws IOException in case of failure
555      * @deprecated always specify a character encoding
556      */
557     @Deprecated
558     public static void copy( @Nonnull final String input, @Nonnull final OutputStream output, final int bufferSize )
559         throws IOException
560     {
561         final StringReader in = new StringReader( input );
562         final OutputStreamWriter out = new OutputStreamWriter( output );
563         copy( in, out, bufferSize );
564         // NOTE: Unless anyone is planning on rewriting OutputStreamWriter, we have to flush
565         // here.
566         out.flush();
567     }
568 
569     ///////////////////////////////////////////////////////////////
570     // String -> Writer
571 
572     /**
573      * Copy chars from a <code>String</code> to a <code>Writer</code>.
574      * 
575      * @param input the string to write
576      * @param output resulting output {@link Writer}
577      * @throws IOException in case of failure
578      * @deprecated use {@code org.apache.commons.io.IOUtils.write()}.
579      */
580     @Deprecated
581     public static void copy( @Nonnull final String input, @Nonnull final Writer output )
582         throws IOException
583     {
584         output.write( input );
585     }
586 
587     ///////////////////////////////////////////////////////////////
588     // String -> byte[]
589 
590     /**
591      * Get the contents of a <code>String</code> as a <code>byte[]</code>.
592      * 
593      * @param input the String to read from
594      * @return the resulting byte array
595      * @throws IOException in case of failure
596      * @deprecated always specify a character encoding
597      */
598     @Deprecated
599     @Nonnull public static byte[] toByteArray( @Nonnull final String input )
600         throws IOException
601     {
602         return toByteArray( input, DEFAULT_BUFFER_SIZE );
603     }
604 
605     /**
606      * Get the contents of a <code>String</code> as a <code>byte[]</code>.
607      *
608      * @param input the InputStream to read from
609      * @param bufferSize size of internal buffer
610      * @return the resulting byte array
611      * @throws IOException in case of failure
612      * @deprecated always specify a character encoding
613      */
614     @Deprecated
615     @Nonnull public static byte[] toByteArray( @Nonnull final String input, final int bufferSize )
616         throws IOException
617     {
618         ByteArrayOutputStream output = new ByteArrayOutputStream();
619         copy( input, output, bufferSize );
620         return output.toByteArray();
621     }
622 
623     ///////////////////////////////////////////////////////////////
624     // Derived copy methods
625     // byte[] -> *
626     ///////////////////////////////////////////////////////////////
627 
628     ///////////////////////////////////////////////////////////////
629     // byte[] -> Writer
630 
631     /**
632      * Copy and convert bytes from a <code>byte[]</code> to chars on a
633      * <code>Writer</code>.
634      * The platform's default encoding is used for the byte-to-char conversion.
635      * 
636      * @param input the InputStream to read from
637      * @param output the output to write to
638      * @throws IOException in case of failure
639      * @deprecated always specify a character encoding
640      */
641     @Deprecated
642     public static void copy( @Nonnull final byte[] input, @Nonnull final Writer output )
643         throws IOException
644     {
645         copy( input, output, DEFAULT_BUFFER_SIZE );
646     }
647 
648     /**
649      * Copy and convert bytes from a <code>byte[]</code> to chars on a
650      * <code>Writer</code>.
651      * The platform's default encoding is used for the byte-to-char conversion.
652      *
653      * @param input the InputStream to read from
654      * @param output the output to write to
655      * @param bufferSize size of internal buffer
656      * @throws IOException in case of failure
657      * @deprecated always specify a character encoding
658      */
659     @Deprecated
660     public static void copy( @Nonnull final byte[] input, @Nonnull final Writer output, final int bufferSize )
661         throws IOException
662     {
663         final ByteArrayInputStream in = new ByteArrayInputStream( input );
664         copy( in, output, bufferSize );
665     }
666 
667     /**
668      * Copy and convert bytes from a <code>byte[]</code> to chars on a
669      * <code>Writer</code>, using the specified encoding.
670      *
671      * @param encoding the name of a supported character encoding. See the
672      *                 <a href="https://www.iana.org/assignments/character-sets">IANA
673      *                 Charset Registry</a> for a list of valid encoding types.
674      * @param input the data to write
675      * @param output the writer to write to
676      * @throws IOException in case of failure
677      * @deprecated use {@code org.apache.commons.io.IOUtils.write()}.
678      */
679     @Deprecated
680     public static void copy( @Nonnull final byte[] input, @Nonnull final Writer output, final String encoding )
681         throws IOException
682     {
683         final ByteArrayInputStream in = new ByteArrayInputStream( input );
684         copy( in, output, encoding );
685     }
686 
687     /**
688      * Copy and convert bytes from a <code>byte[]</code> to chars on a
689      * <code>Writer</code>, using the specified encoding.
690      *
691      * @param encoding   the name of a supported character encoding. See the
692      *                   <a href="https://www.iana.org/assignments/character-sets">IANA
693      *                   Charset Registry</a> for a list of valid encoding types.
694      * @param input the input bytes
695      * @param output The output buffer {@link Writer}
696      * @param bufferSize size of internal buffer
697      * @throws IOException in case of failure
698      * @deprecated use {@code org.apache.commons.io.IOUtils.write()}.
699      */
700     @Deprecated
701     public static void copy( @Nonnull final byte[] input, @Nonnull final Writer output, @Nonnull final String encoding,
702                              final int bufferSize )
703         throws IOException
704     {
705         final ByteArrayInputStream in = new ByteArrayInputStream( input );
706         copy( in, output, encoding, bufferSize );
707     }
708 
709     ///////////////////////////////////////////////////////////////
710     // byte[] -> String
711 
712     /**
713      * Get the contents of a <code>byte[]</code> as a String.
714      * The platform's default encoding is used for the byte-to-char conversion.
715      * @param input the input bytes
716      * @return the resulting string
717      * @throws IOException in case of failure
718      * @deprecated always specify a character encoding
719      */
720     @Deprecated
721     @Nonnull public static String toString( @Nonnull final byte[] input )
722         throws IOException
723     {
724         return toString( input, DEFAULT_BUFFER_SIZE );
725     }
726 
727     /**
728      * Get the contents of a <code>byte[]</code> as a String.
729      * The platform's default encoding is used for the byte-to-char conversion.
730      *
731      * @param bufferSize size of internal buffer
732      * @param input the input bytes
733      * @return the created string
734      * @throws IOException in case of failure
735      * @deprecated always specify a character encoding
736      */
737     @Deprecated
738     @Nonnull public static String toString( @Nonnull final byte[] input, final int bufferSize )
739         throws IOException
740     {
741         final StringWriter sw = new StringWriter();
742         copy( input, sw, bufferSize );
743         return sw.toString();
744     }
745 
746     /**
747      * Get the contents of a <code>byte[]</code> as a String.
748      *
749      * @param encoding the name of a supported character encoding. See the
750      *                 <a href="https://www.iana.org/assignments/character-sets">IANA
751      *                 Charset Registry</a> for a list of valid encoding types.
752      * @param input the input bytes
753      * @return the resulting string
754      * @throws IOException in case of failure
755      * @deprecated use {@code new String(input, encoding)}
756      */
757     @Deprecated
758     @Nonnull public static String toString( @Nonnull final byte[] input, @Nonnull final String encoding )
759         throws IOException
760     {
761         return toString( input, encoding, DEFAULT_BUFFER_SIZE );
762     }
763 
764     /**
765      * Get the contents of a <code>byte[]</code> as a String.
766      *
767      * @param encoding   the name of a supported character encoding. See the
768      *                   <a href="https://www.iana.org/assignments/character-sets">IANA
769      *                   Charset Registry</a> for a list of valid encoding types.
770      * @param bufferSize size of internal buffer
771      * @param input input bytes
772      * @return the resulting string
773      * @throws IOException in case of failure
774      * @deprecated use {@code new String(input, encoding)}
775      */
776     @Deprecated
777     @Nonnull public static String toString( @Nonnull final byte[] input, @Nonnull final String encoding,
778                                             final int bufferSize )
779         throws IOException
780     {
781         final StringWriter sw = new StringWriter();
782         copy( input, sw, encoding, bufferSize );
783         return sw.toString();
784     }
785 
786     ///////////////////////////////////////////////////////////////
787     // byte[] -> OutputStream
788 
789     /**
790      * Copy bytes from a <code>byte[]</code> to an <code>OutputStream</code>.
791      * 
792      * @param input Input byte array.
793      * @param output output stream {@link OutputStream}
794      * @throws IOException in case of failure
795      * @deprecated inline this method
796      */
797     @Deprecated
798     public static void copy( @Nonnull final byte[] input, @Nonnull final OutputStream output )
799         throws IOException
800     {
801         output.write( input );
802     }
803 
804     /**
805      * Compare the contents of two streams to determine if they are equal or not.
806      *
807      * @param input1 the first stream
808      * @param input2 the second stream
809      * @return true if the content of the streams are equal or they both don't exist, false otherwise
810      * @throws IOException in case of failure
811      * @deprecated use {@code org.apache.commons.io.IOUtils.contentEquals()}
812      */
813     @Deprecated
814     public static boolean contentEquals( @Nonnull final InputStream input1, @Nonnull final InputStream input2 )
815         throws IOException
816     {
817         final InputStream bufferedInput1 = new BufferedInputStream( input1 );
818         final InputStream bufferedInput2 = new BufferedInputStream( input2 );
819 
820         int ch = bufferedInput1.read();
821         while ( -1 != ch )
822         {
823             final int ch2 = bufferedInput2.read();
824             if ( ch != ch2 )
825             {
826                 return false;
827             }
828             ch = bufferedInput1.read();
829         }
830 
831         final int ch2 = bufferedInput2.read();
832         return -1 == ch2;
833     }
834 
835     // ----------------------------------------------------------------------
836     // closeXXX()
837     // ----------------------------------------------------------------------
838 
839     /**
840      * Closes a {@code Channel} suppressing any {@code IOException}.
841      * <p>
842      * <b>Note:</b> The use case justifying this method is a shortcoming of the Java language up to but not including
843      * Java 7. For any code targeting Java 7 or later use of this method is highly discouraged and the
844      * {@code try-with-resources} statement should be used instead. Care must be taken to not use this method in a way
845      * {@code IOException}s get suppressed incorrectly.
846      * <strong>You must close all resources in use inside the {@code try} block to not suppress exceptions in the
847      * {@code finally} block incorrectly by using this method.</strong>
848      * </p>
849      * <p>
850      * <b>Example:</b><br/>
851      * <pre>
852      * // Introduce variables for the resources and initialize them to null. This cannot throw an exception.
853      * Closeable resource1 = null;
854      * Closeable resource2 = null;
855      * try
856      * {
857      *     // Obtain a resource object and assign it to variable resource1. This may throw an exception.
858      *     // If successful, resource1 != null.
859      *     resource1 = ...
860      *
861      *     // Obtain a resource object and assign it to variable resource2. This may throw an exception.
862      *     // If successful, resource2 != null. Not reached if an exception has been thrown above.
863      *     resource2 = ...
864      *
865      *     // Perform operations on the resources. This may throw an exception. Not reached if an exception has been
866      *     // thrown above. Note: Treat the variables resource1 and resource2 the same way as if they would have been
867      *     // declared with the final modifier - that is - do NOT write anyting like resource1 = something else or
868      *     // resource2 = something else here.
869      *     resource1 ...
870      *     resource2 ...
871      *
872      *     // Finally, close the resources and set the variables to null indicating successful completion.
873      *     // This may throw an exception. Not reached if an exception has been thrown above.
874      *     resource1.close();
875      *     resource1 = null;
876      *     // Not reached if an exception has been thrown above.
877      *     resource2.close();
878      *     resource2 = null;
879      *
880      *     // All resources are closed at this point and all operations (up to here) completed successfully without
881      *     // throwing an exception we would need to handle (by letting it propagate or by catching and handling it).
882      * }
883      * finally
884      * {
885      *     // Cleanup any resource not closed in the try block due to an exception having been thrown and suppress any
886      *     // exception this may produce to not stop the exception from the try block to be propagated. If the try
887      *     // block completed successfully, all variables will have been set to null there and this will not do
888      *     // anything. This is just to cleanup properly in case of an exception.
889      *
890      *     IOUtil.close( resource1 );
891      *     IOUtil.close( resource2 );
892      *
893      *     // Without that utility method you would need to write the following:
894      *     //
895      *     // try
896      *     // {
897      *     //     if ( resource1 != null )
898      *     //     {
899      *     //         resource1.close();
900      *     //     }
901      *     // }
902      *     // catch( IOException e )
903      *     // {
904      *     //     Suppressed. If resource1 != null, an exception has already been thrown in the try block we need to
905      *     //     propagate instead of this one.
906      *     // }
907      *     // finally
908      *     // {
909      *     //     try
910      *     //     {
911      *     //         if ( resource2 != null )
912      *     //         {
913      *     //             resource2.close();
914      *     //         }
915      *     //     }
916      *     //     catch ( IOException e )
917      *     //     {
918      *     //         Suppressed. If resource2 != null, an exception has already been thrown in the try block we need to
919      *     //         propagate instead of this one.
920      *     //     }
921      *     // }
922      * }
923      * </pre>
924      * </p>
925      *
926      * @param channel The channel to close or {@code null}.
927      * @deprecated use try-with-resources
928      */
929     @Deprecated
930     public static void close( @Nullable Channel channel )
931     {
932         try
933         {
934             if ( channel != null )
935             {
936                 channel.close();
937             }
938         }
939         catch ( IOException ex )
940         {
941             // Suppressed
942         }
943     }
944 
945     /**
946      * Closes an {@code InputStream} suppressing any {@code IOException}.
947      * <p>
948      * <b>Note:</b> The use case justifying this method is a shortcoming of the Java language up to but not including
949      * Java 7. For any code targeting Java 7 or later use of this method is highly discouraged and the
950      * {@code try-with-resources} statement should be used instead. Care must be taken to not use this method in a way
951      * {@code IOException}s get suppressed incorrectly.
952      * <strong>You must close all resources in use inside the {@code try} block to not suppress exceptions in the
953      * {@code finally} block incorrectly by using this method.</strong>
954      * </p>
955      * <p>
956      * <b>Example:</b><br/>
957      * <pre>
958      * // Introduce variables for the resources and initialize them to null. This cannot throw an exception.
959      * Closeable resource1 = null;
960      * Closeable resource2 = null;
961      * try
962      * {
963      *     // Obtain a resource object and assign it to variable resource1. This may throw an exception.
964      *     // If successful, resource1 != null.
965      *     resource1 = ...
966      *
967      *     // Obtain a resource object and assign it to variable resource2. This may throw an exception.
968      *     // If successful, resource2 != null. Not reached if an exception has been thrown above.
969      *     resource2 = ...
970      *
971      *     // Perform operations on the resources. This may throw an exception. Not reached if an exception has been
972      *     // thrown above. Note: Treat the variables resource1 and resource2 the same way as if they would have been
973      *     // declared with the final modifier - that is - do NOT write anyting like resource1 = something else or
974      *     // resource2 = something else here.
975      *     resource1 ...
976      *     resource2 ...
977      *
978      *     // Finally, close the resources and set the variables to null indicating successful completion.
979      *     // This may throw an exception. Not reached if an exception has been thrown above.
980      *     resource1.close();
981      *     resource1 = null;
982      *     // This may throw an exception. Not reached if an exception has been thrown above.
983      *     resource2.close();
984      *     resource2 = null;
985      *
986      *     // All resources are closed at this point and all operations (up to here) completed successfully without
987      *     // throwing an exception we would need to handle (by letting it propagate or by catching and handling it).
988      * }
989      * finally
990      * {
991      *     // Cleanup any resource not closed in the try block due to an exception having been thrown and suppress any
992      *     // exception this may produce to not stop the exception from the try block to be propagated. If the try
993      *     // block completed successfully, all variables will have been set to null there and this will not do
994      *     // anything. This is just to cleanup properly in case of an exception.
995      *
996      *     IOUtil.close( resource1 );
997      *     IOUtil.close( resource2 );
998      *
999      *     // Without that utility method you would need to write the following:
1000      *     //
1001      *     // try
1002      *     // {
1003      *     //     if ( resource1 != null )
1004      *     //     {
1005      *     //         resource1.close();
1006      *     //     }
1007      *     // }
1008      *     // catch( IOException e )
1009      *     // {
1010      *     //     Suppressed. If resource1 != null, an exception has already been thrown in the try block we need to
1011      *     //     propagate instead of this one.
1012      *     // }
1013      *     // finally
1014      *     // {
1015      *     //     try
1016      *     //     {
1017      *     //         if ( resource2 != null )
1018      *     //         {
1019      *     //             resource2.close();
1020      *     //         }
1021      *     //     }
1022      *     //     catch ( IOException e )
1023      *     //     {
1024      *     //         Suppressed. If resource2 != null, an exception has already been thrown in the try block we need to
1025      *     //         propagate instead of this one.
1026      *     //     }
1027      *     // }
1028      * }
1029      * </pre>
1030      * </p>
1031      *
1032      * @param inputStream The stream to close or {@code null}.
1033      * @deprecated use try-with-resources
1034      */
1035     @Deprecated
1036     public static void close( @Nullable InputStream inputStream )
1037     {
1038         try
1039         {
1040             if ( inputStream != null )
1041             {
1042                 inputStream.close();
1043             }
1044         }
1045         catch ( IOException ex )
1046         {
1047             // Suppressed
1048         }
1049     }
1050 
1051     /**
1052      * Closes an {@code OutputStream} suppressing any {@code IOException}.
1053      * <p>
1054      * <b>Note:</b> The use case justifying this method is a shortcoming of the Java language up to but not including
1055      * Java 7. For any code targeting Java 7 or later use of this method is highly discouraged and the
1056      * {@code try-with-resources} statement should be used instead. Care must be taken to not use this method in a way
1057      * {@code IOException}s get suppressed incorrectly.
1058      * <strong>You must close all resources in use inside the {@code try} block to not suppress exceptions in the
1059      * {@code finally} block incorrectly by using this method.</strong>
1060      * </p>
1061      * <p>
1062      * <b>Example:</b><br/>
1063      * <pre>
1064      * // Introduce variables for the resources and initialize them to null. This cannot throw an exception.
1065      * Closeable resource1 = null;
1066      * Closeable resource2 = null;
1067      * try
1068      * {
1069      *     // Obtain a resource object and assign it to variable resource1. This may throw an exception.
1070      *     // If successful, resource1 != null.
1071      *     resource1 = ...
1072      *
1073      *     // Obtain a resource object and assign it to variable resource2. This may throw an exception.
1074      *     // If successful, resource2 != null. Not reached if an exception has been thrown above.
1075      *     resource2 = ...
1076      *
1077      *     // Perform operations on the resources. This may throw an exception. Not reached if an exception has been
1078      *     // thrown above. Note: Treat the variables resource1 and resource2 the same way as if they would have been
1079      *     // declared with the final modifier - that is - do NOT write anyting like resource1 = something else or
1080      *     // resource2 = something else here.
1081      *     resource1 ...
1082      *     resource2 ...
1083      *
1084      *     // Finally, close the resources and set the variables to null indicating successful completion.
1085      *     // This may throw an exception. Not reached if an exception has been thrown above.
1086      *     resource1.close();
1087      *     resource1 = null;
1088      *     // This may throw an exception. Not reached if an exception has been thrown above.
1089      *     resource2.close();
1090      *     resource2 = null;
1091      *
1092      *     // All resources are closed at this point and all operations (up to here) completed successfully without
1093      *     // throwing an exception we would need to handle (by letting it propagate or by catching and handling it).
1094      * }
1095      * finally
1096      * {
1097      *     // Cleanup any resource not closed in the try block due to an exception having been thrown and suppress any
1098      *     // exception this may produce to not stop the exception from the try block to be propagated. If the try
1099      *     // block completed successfully, all variables will have been set to null there and this will not do
1100      *     // anything. This is just to cleanup properly in case of an exception.
1101      *
1102      *     IOUtil.close( resource1 );
1103      *     IOUtil.close( resource2 );
1104      *
1105      *     // Without that utility method you would need to write the following:
1106      *     //
1107      *     // try
1108      *     // {
1109      *     //     if ( resource1 != null )
1110      *     //     {
1111      *     //         resource1.close();
1112      *     //     }
1113      *     // }
1114      *     // catch( IOException e )
1115      *     // {
1116      *     //     Suppressed. If resource1 != null, an exception has already been thrown in the try block we need to
1117      *     //     propagate instead of this one.
1118      *     // }
1119      *     // finally
1120      *     // {
1121      *     //     try
1122      *     //     {
1123      *     //         if ( resource2 != null )
1124      *     //         {
1125      *     //             resource2.close();
1126      *     //         }
1127      *     //     }
1128      *     //     catch ( IOException e )
1129      *     //     {
1130      *     //         Suppressed. If resource2 != null, an exception has already been thrown in the try block we need to
1131      *     //         propagate instead of this one.
1132      *     //     }
1133      *     // }
1134      * }
1135      * </pre>
1136      * </p>
1137      *
1138      * @param outputStream The stream to close or {@code null}.
1139      * @deprecated use try-with-resources
1140      */
1141     @Deprecated
1142     public static void close( @Nullable OutputStream outputStream )
1143     {
1144         try
1145         {
1146             if ( outputStream != null )
1147             {
1148                 outputStream.close();
1149             }
1150         }
1151         catch ( IOException ex )
1152         {
1153             // Suppressed
1154         }
1155     }
1156 
1157     /**
1158      * Closes a {@code Reader} suppressing any {@code IOException}.
1159      * <p>
1160      * <b>Note:</b> The use case justifying this method is a shortcoming of the Java language up to but not including
1161      * Java 7. For any code targeting Java 7 or later use of this method is highly discouraged and the
1162      * {@code try-with-resources} statement should be used instead. Care must be taken to not use this method in a way
1163      * {@code IOException}s get suppressed incorrectly.
1164      * <strong>You must close all resources in use inside the {@code try} block to not suppress exceptions in the
1165      * {@code finally} block incorrectly by using this method.</strong>
1166      * </p>
1167      * <p>
1168      * <b>Example:</b><br/>
1169      * <pre>
1170      * // Introduce variables for the resources and initialize them to null. This cannot throw an exception.
1171      * Closeable resource1 = null;
1172      * Closeable resource2 = null;
1173      * try
1174      * {
1175      *     // Obtain a resource object and assign it to variable resource1. This may throw an exception.
1176      *     // If successful, resource1 != null.
1177      *     resource1 = ...
1178      *
1179      *     // Obtain a resource object and assign it to variable resource2. This may throw an exception.
1180      *     // If successful, resource2 != null. Not reached if an exception has been thrown above.
1181      *     resource2 = ...
1182      *
1183      *     // Perform operations on the resources. This may throw an exception. Not reached if an exception has been
1184      *     // thrown above. Note: Treat the variables resource1 and resource2 the same way as if they would have been
1185      *     // declared with the final modifier - that is - do NOT write anyting like resource1 = something else or
1186      *     // resource2 = something else here.
1187      *     resource1 ...
1188      *     resource2 ...
1189      *
1190      *     // Finally, close the resources and set the variables to null indicating successful completion.
1191      *     // This may throw an exception. Not reached if an exception has been thrown above.
1192      *     resource1.close();
1193      *     resource1 = null;
1194      *     // This may throw an exception. Not reached if an exception has been thrown above.
1195      *     resource2.close();
1196      *     resource2 = null;
1197      *
1198      *     // All resources are closed at this point and all operations (up to here) completed successfully without
1199      *     // throwing an exception we would need to handle (by letting it propagate or by catching and handling it).
1200      * }
1201      * finally
1202      * {
1203      *     // Cleanup any resource not closed in the try block due to an exception having been thrown and suppress any
1204      *     // exception this may produce to not stop the exception from the try block to be propagated. If the try
1205      *     // block completed successfully, all variables will have been set to null there and this will not do
1206      *     // anything. This is just to cleanup properly in case of an exception.
1207      *
1208      *     IOUtil.close( resource1 );
1209      *     IOUtil.close( resource2 );
1210      *
1211      *     // Without that utility method you would need to write the following:
1212      *     //
1213      *     // try
1214      *     // {
1215      *     //     if ( resource1 != null )
1216      *     //     {
1217      *     //         resource1.close();
1218      *     //     }
1219      *     // }
1220      *     // catch( IOException e )
1221      *     // {
1222      *     //     Suppressed. If resource1 != null, an exception has already been thrown in the try block we need to
1223      *     //     propagate instead of this one.
1224      *     // }
1225      *     // finally
1226      *     // {
1227      *     //     try
1228      *     //     {
1229      *     //         if ( resource2 != null )
1230      *     //         {
1231      *     //             resource2.close();
1232      *     //         }
1233      *     //     }
1234      *     //     catch ( IOException e )
1235      *     //     {
1236      *     //         Suppressed. If resource2 != null, an exception has already been thrown in the try block we need to
1237      *     //         propagate instead of this one.
1238      *     //     }
1239      *     // }
1240      * }
1241      * </pre>
1242      * </p>
1243      *
1244      * @param reader The reader to close or {@code null}.
1245      * @deprecated use try-with-resources
1246      */
1247     @Deprecated
1248     public static void close( @Nullable Reader reader )
1249     {
1250         try
1251         {
1252             if ( reader != null )
1253             {
1254                 reader.close();
1255             }
1256         }
1257         catch ( IOException ex )
1258         {
1259             // Suppressed
1260         }
1261     }
1262 
1263     /**
1264      * Closes a {@code Writer} suppressing any {@code IOException}.
1265      * <p>
1266      * <b>Note:</b> The use case justifying this method is a shortcoming of the Java language up to but not including
1267      * Java 7. For any code targeting Java 7 or later use of this method is highly discouraged and the
1268      * {@code try-with-resources} statement should be used instead. Care must be taken to not use this method in a way
1269      * {@code IOException}s get suppressed incorrectly.
1270      * <strong>You must close all resources in use inside the {@code try} block to not suppress exceptions in the
1271      * {@code finally} block incorrectly by using this method.</strong>
1272      * </p>
1273      * <p>
1274      * <b>Example:</b><br/>
1275      * <pre>
1276      * // Introduce variables for the resources and initialize them to null. This cannot throw an exception.
1277      * Closeable resource1 = null;
1278      * Closeable resource2 = null;
1279      * try
1280      * {
1281      *     // Obtain a resource object and assign it to variable resource1. This may throw an exception.
1282      *     // If successful, resource1 != null.
1283      *     resource1 = ...
1284      *
1285      *     // Obtain a resource object and assign it to variable resource2. This may throw an exception.
1286      *     // If successful, resource2 != null. Not reached if an exception has been thrown above.
1287      *     resource2 = ...
1288      *
1289      *     // Perform operations on the resources. This may throw an exception. Not reached if an exception has been
1290      *     // thrown above. Note: Treat the variables resource1 and resource2 the same way as if they would have been
1291      *     // declared with the final modifier - that is - do NOT write anyting like resource1 = something else or
1292      *     // resource2 = something else here.
1293      *     resource1 ...
1294      *     resource2 ...
1295      *
1296      *     // Finally, close the resources and set the variables to null indicating successful completion.
1297      *     // This may throw an exception. Not reached if an exception has been thrown above.
1298      *     resource1.close();
1299      *     resource1 = null;
1300      *     // This may throw an exception. Not reached if an exception has been thrown above.
1301      *     resource2.close();
1302      *     resource2 = null;
1303      *
1304      *     // All resources are closed at this point and all operations (up to here) completed successfully without
1305      *     // throwing an exception we would need to handle (by letting it propagate or by catching and handling it).
1306      * }
1307      * finally
1308      * {
1309      *     // Cleanup any resource not closed in the try block due to an exception having been thrown and suppress any
1310      *     // exception this may produce to not stop the exception from the try block to be propagated. If the try
1311      *     // block completed successfully, all variables will have been set to null there and this will not do
1312      *     // anything. This is just to cleanup properly in case of an exception.
1313      *
1314      *     IOUtil.close( resource1 );
1315      *     IOUtil.close( resource2 );
1316      *
1317      *     // Without that utility method you would need to write the following:
1318      *     //
1319      *     // try
1320      *     // {
1321      *     //     if ( resource1 != null )
1322      *     //     {
1323      *     //         resource1.close();
1324      *     //     }
1325      *     // }
1326      *     // catch( IOException e )
1327      *     // {
1328      *     //     Suppressed. If resource1 != null, an exception has already been thrown in the try block we need to
1329      *     //     propagate instead of this one.
1330      *     // }
1331      *     // finally
1332      *     // {
1333      *     //     try
1334      *     //     {
1335      *     //         if ( resource2 != null )
1336      *     //         {
1337      *     //             resource2.close();
1338      *     //         }
1339      *     //     }
1340      *     //     catch ( IOException e )
1341      *     //     {
1342      *     //         Suppressed. If resource2 != null, an exception has already been thrown in the try block we need to
1343      *     //         propagate instead of this one.
1344      *     //     }
1345      *     // }
1346      * }
1347      * </pre>
1348      * </p>
1349      *
1350      * @param writer The writer to close or {@code null}.
1351      * @deprecated use try-with-resources
1352      */
1353     @Deprecated
1354     public static void close( @Nullable Writer writer )
1355     {
1356         try
1357         {
1358             if ( writer != null )
1359             {
1360                 writer.close();
1361             }
1362         }
1363         catch ( IOException ex )
1364         {
1365             // Suppressed
1366         }
1367     }
1368 }