View Javadoc
1   /*
2    *   Licensed to the Apache Software Foundation (ASF) under one
3    *   or more contributor license agreements.  See the NOTICE file
4    *   distributed with this work for additional information
5    *   regarding copyright ownership.  The ASF licenses this file
6    *   to you under the Apache License, Version 2.0 (the
7    *   "License"); you may not use this file except in compliance
8    *   with the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   *   Unless required by applicable law or agreed to in writing,
13   *   software distributed under the License is distributed on an
14   *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   *   KIND, either express or implied.  See the License for the
16   *   specific language governing permissions and limitations
17   *   under the License.
18   *
19   */
20  
21  package org.apache.directory.api.util;
22  
23  
24  import java.io.BufferedReader;
25  import java.io.Closeable;
26  import java.io.IOException;
27  import java.io.InputStream;
28  import java.io.InputStreamReader;
29  import java.io.OutputStream;
30  import java.io.Reader;
31  import java.io.Writer;
32  import java.nio.charset.Charset;
33  import java.util.ArrayList;
34  import java.util.List;
35  
36  
37  /**
38   * This code comes from Apache commons.io library.
39   * 
40   * Origin of code: Excalibur, Alexandria, Tomcat, Commons-Utils.
41   *
42   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
43   */
44  public final class IOUtils
45  {
46      /**
47       * The default buffer size ({@value}) to use for
48       * {@link #copyLarge(InputStream, OutputStream)}
49       * and
50       * {@link #copyLarge(Reader, Writer)}
51       */
52      private static final int DEFAULT_BUFFER_SIZE = 1024 * 4;
53  
54      /** The end of file */
55      private static final int EOF = -1;
56  
57  
58      /**
59       * Creates a new instance of FileUtils.
60       */
61      private IOUtils()
62      {
63          // Nothing to do.
64      }
65  
66  
67      /**
68      * Closes an <code>InputStream</code> unconditionally.
69      * <p>
70      * Equivalent to {@link InputStream#close()}, except any exceptions will be ignored.
71      * This is typically used in finally blocks.
72      * <p>
73      * Example code:
74      * <pre>
75      *   byte[] data = new byte[1024];
76      *   InputStream in = null;
77      *   try {
78      *       in = new FileInputStream("foo.txt");
79      *       in.read(data);
80      *       in.close(); //close errors are handled
81      *   } catch (Exception e) {
82      *       // error handling
83      *   } finally {
84      *       IOUtils.closeQuietly(in);
85      *   }
86      * </pre>
87      *
88      * @param input  the InputStream to close, may be null or already closed
89      */
90      public static void closeQuietly( InputStream input )
91      {
92          closeQuietly( ( Closeable ) input );
93      }
94  
95  
96      /**
97       * Closes a <code>Closeable</code> unconditionally.
98       * <p>
99       * Equivalent to {@link Closeable#close()}, except any exceptions will be ignored. This is typically used in
100      * finally blocks.
101      * <p>
102      * Example code:
103      * 
104      * <pre>
105      * Closeable closeable = null;
106      * try {
107      *     closeable = new FileReader(&quot;foo.txt&quot;);
108      *     // process closeable
109      *     closeable.close();
110      * } catch (Exception e) {
111      *     // error handling
112      * } finally {
113      *     IOUtils.closeQuietly(closeable);
114      * }
115      * </pre>
116      * 
117      * Closing all streams:
118      * 
119      * <pre>
120      * try {
121      *     return IOUtils.copy(inputStream, outputStream);
122      * } finally {
123      *     IOUtils.closeQuietly(inputStream);
124      *     IOUtils.closeQuietly(outputStream);
125      * }
126      * </pre>
127      * 
128      * @param closeables the objects to close, may be null or already closed
129      * @since 2.5
130      */
131     public static void closeQuietly( Closeable... closeables )
132     {
133         if ( closeables == null )
134         {
135             return;
136         }
137 
138         for ( Closeable closeable : closeables )
139         {
140             closeQuietly( closeable );
141         }
142     }
143 
144 
145     /**
146      * Closes a <code>Closeable</code> unconditionally.
147      * <p>
148      * Equivalent to {@link Closeable#close()}, except any exceptions will be ignored. This is typically used in
149      * finally blocks.
150      * <p>
151      * Example code:
152      * 
153      * <pre>
154      * Closeable closeable = null;
155      * try {
156      *     closeable = new FileReader(&quot;foo.txt&quot;);
157      *     // process closeable
158      *     closeable.close();
159      * } catch (Exception e) {
160      *     // error handling
161      * } finally {
162      *     IOUtils.closeQuietly(closeable);
163      * }
164      * </pre>
165      * 
166      * Closing all streams:
167      * 
168      * <pre>
169      * try {
170      *     return IOUtils.copy(inputStream, outputStream);
171      * } finally {
172      *     IOUtils.closeQuietly(inputStream);
173      *     IOUtils.closeQuietly(outputStream);
174      * }
175      * </pre>
176      * 
177      * @param closeable
178      *            the objects to close, may be null or already closed
179      * @since 2.0
180      */
181     public static void closeQuietly( Closeable closeable )
182     {
183         try
184         {
185             if ( closeable != null )
186             {
187                 closeable.close();
188             }
189         }
190         catch ( IOException ioe )
191         {
192             // ignore
193         }
194     }
195 
196 
197     /**
198     * Gets the contents of an <code>InputStream</code> as a String
199     * using the specified character encoding.
200     * <p>
201     * This method buffers the input internally, so there is no need to use a
202     * <code>BufferedInputStream</code>.
203     * </p>
204     * @param input  the <code>InputStream</code> to read from
205     * @param encoding  the encoding to use, null means platform default
206     * @return the requested String
207     * @throws NullPointerException if the input is null
208     * @throws IOException if an I/O error occurs
209     * @since 2.3
210     */
211     public static String toString( InputStream input, Charset encoding ) throws IOException
212     {
213         StringBuilderWriter sw = new StringBuilderWriter();
214         copy( input, sw, encoding );
215 
216         return sw.toString();
217     }
218 
219 
220     /**
221      * Returns the given Charset or the default Charset if the given Charset is null.
222      * 
223      * @param charset A charset or null.
224      * @return the given Charset or the default Charset if the given Charset is null
225      */
226     public static Charset toCharset( Charset charset )
227     {
228         return charset == null ? Charset.defaultCharset() : charset;
229     }
230 
231 
232     /**
233      * Returns a Charset for the named charset. If the name is null, return the default Charset.
234      * 
235      * @param charset The name of the requested charset, may be null.
236      * @return a Charset for the named charset
237      */
238     public static Charset toCharset( String charset )
239     {
240         return charset == null ? Charset.defaultCharset() : Charset.forName( charset );
241     }
242 
243 
244     /**
245      * Copies bytes from an <code>InputStream</code> to chars on a
246      * <code>Writer</code> using the specified character encoding.
247      * <p>
248      * This method buffers the input internally, so there is no need to use a
249      * <code>BufferedInputStream</code>.
250      * <p>
251      * This method uses {@link InputStreamReader}.
252      *
253      * @param input  the <code>InputStream</code> to read from
254      * @param output  the <code>Writer</code> to write to
255      * @param inputEncoding  the encoding to use for the input stream, null means platform default
256      * @throws NullPointerException if the input or output is null
257      * @throws IOException if an I/O error occurs
258      * @since 2.3
259      */
260     public static void copy( InputStream input, Writer output, Charset inputEncoding ) throws IOException
261     {
262         InputStreamReader in = new InputStreamReader( input, toCharset( inputEncoding ) );
263         copy( in, output );
264     }
265 
266 
267     /**
268      * Copies chars from a <code>Reader</code> to a <code>Writer</code>.
269      * <p>
270      * This method buffers the input internally, so there is no need to use a
271      * <code>BufferedReader</code>.
272      * <p>
273      * Large streams (over 2GB) will return a chars copied value of
274      * <code>-1</code> after the copy has completed since the correct
275      * number of chars cannot be returned as an int. For large streams
276      * use the <code>copyLarge(Reader, Writer)</code> method.
277      *
278      * @param input  the <code>Reader</code> to read from
279      * @param output  the <code>Writer</code> to write to
280      * @return the number of characters copied, or -1 if &gt; Integer.MAX_VALUE
281      * @throws NullPointerException if the input or output is null
282      * @throws IOException if an I/O error occurs
283      * @since 1.1
284      */
285     public static int copy( Reader input, Writer output ) throws IOException
286     {
287         long count = copyLarge( input, output );
288 
289         if ( count > Integer.MAX_VALUE )
290         {
291             return -1;
292         }
293 
294         return ( int ) count;
295     }
296 
297     
298     /**
299      * Copies bytes from an <code>InputStream</code> to an
300      * <code>OutputStream</code>.
301      * <p>
302      * This method buffers the input internally, so there is no need to use a
303      * <code>BufferedInputStream</code>.
304      * <p>
305      * Large streams (over 2GB) will return a bytes copied value of
306      * <code>-1</code> after the copy has completed since the correct
307      * number of bytes cannot be returned as an int. For large streams
308      * use the <code>copyLarge(InputStream, OutputStream)</code> method.
309      *
310      * @param input  the <code>InputStream</code> to read from
311      * @param output  the <code>OutputStream</code> to write to
312      * @return the number of bytes copied, or -1 if &gt; Integer.MAX_VALUE
313      * @throws NullPointerException if the input or output is null
314      * @throws IOException if an I/O error occurs
315      * @since 1.1
316      */
317     public static int copy( InputStream input, OutputStream output ) throws IOException 
318     {
319         long count = copyLarge( input, output );
320         
321         if ( count > Integer.MAX_VALUE ) 
322         {
323             return -1;
324         }
325         
326         return ( int ) count;
327     }
328     
329     
330     /**
331      * Copies bytes from an <code>InputStream</code> to an <code>OutputStream</code> using an internal buffer of the
332      * given size.
333      * <p>
334      * This method buffers the input internally, so there is no need to use a <code>BufferedInputStream</code>.
335      * <p>
336      *
337      * @param input
338      *            the <code>InputStream</code> to read from
339      * @param output
340      *            the <code>OutputStream</code> to write to
341      * @param bufferSize
342      *            the bufferSize used to copy from the input to the output
343      * @return the number of bytes copied
344      * @throws NullPointerException
345      *             if the input or output is null
346      * @throws IOException
347      *             if an I/O error occurs
348      * @since 2.5
349      */
350     public static long copy( InputStream input, OutputStream output, int bufferSize ) throws IOException 
351     {
352         return copyLarge( input, output, new byte[bufferSize] );
353     }
354 
355 
356     /**
357      * Copies chars from a large (over 2GB) <code>Reader</code> to a <code>Writer</code>.
358      * <p>
359      * This method buffers the input internally, so there is no need to use a
360      * <code>BufferedReader</code>.
361      * <p>
362      * The buffer size is given by DEFAULT_BUFFER_SIZE.
363      *
364      * @param input  the <code>Reader</code> to read from
365      * @param output  the <code>Writer</code> to write to
366      * @return the number of characters copied
367      * @throws NullPointerException if the input or output is null
368      * @throws IOException if an I/O error occurs
369      * @since 1.3
370      */
371     public static long copyLarge( Reader input, Writer output ) throws IOException
372     {
373         return copyLarge( input, output, new char[DEFAULT_BUFFER_SIZE] );
374     }
375     
376     
377     /**
378      * Copies bytes from a large (over 2GB) <code>InputStream</code> to an
379      * <code>OutputStream</code>.
380      * <p>
381      * This method buffers the input internally, so there is no need to use a
382      * <code>BufferedInputStream</code>.
383      * <p>
384      * The buffer size is given by DEFAULT_BUFFER_SIZE.
385      *
386      * @param input  the <code>InputStream</code> to read from
387      * @param output  the <code>OutputStream</code> to write to
388      * @return the number of bytes copied
389      * @throws NullPointerException if the input or output is null
390      * @throws IOException if an I/O error occurs
391      * @since 1.3
392      */
393     public static long copyLarge( InputStream input, OutputStream output ) throws IOException 
394     {
395         return copy( input, output, DEFAULT_BUFFER_SIZE );
396     }
397 
398     
399     /**
400      * Copies bytes from a large (over 2GB) <code>InputStream</code> to an
401      * <code>OutputStream</code>.
402      * <p>
403      * This method uses the provided buffer, so there is no need to use a
404      * <code>BufferedInputStream</code>.
405      * <p>
406      *
407      * @param input  the <code>InputStream</code> to read from
408      * @param output  the <code>OutputStream</code> to write to
409      * @param buffer the buffer to use for the copy
410      * @return the number of bytes copied
411      * @throws NullPointerException if the input or output is null
412      * @throws IOException if an I/O error occurs
413      * @since 2.2
414      */
415     public static long copyLarge( InputStream input, OutputStream output, byte[] buffer ) throws IOException 
416     {
417         long count = 0;
418         int n = 0;
419         
420         while ( EOF != ( n = input.read( buffer ) ) ) 
421         {
422             output.write( buffer, 0, n );
423             count += n;
424         }
425         
426         return count;
427     }
428 
429 
430     /**
431      * Copies chars from a large (over 2GB) <code>Reader</code> to a <code>Writer</code>.
432      * <p>
433      * This method uses the provided buffer, so there is no need to use a
434      * <code>BufferedReader</code>.
435      * <p>
436      *
437      * @param input  the <code>Reader</code> to read from
438      * @param output  the <code>Writer</code> to write to
439      * @param buffer the buffer to be used for the copy
440      * @return the number of characters copied
441      * @throws NullPointerException if the input or output is null
442      * @throws IOException if an I/O error occurs
443      * @since 2.2
444      */
445     public static long copyLarge( Reader input, Writer output, char[] buffer ) throws IOException
446     {
447         long count = 0;
448         int n = 0;
449 
450         while ( EOF != ( n = input.read( buffer ) ) )
451         {
452             output.write( buffer, 0, n );
453             count += n;
454         }
455 
456         return count;
457     }
458 
459 
460     /**
461      * Writes chars from a <code>String</code> to bytes on an
462      * <code>OutputStream</code> using the specified character encoding.
463      * <p>
464      * This method uses {@link String#getBytes(String)}.
465      *
466      * @param data  the <code>String</code> to write, null ignored
467      * @param output  the <code>OutputStream</code> to write to
468      * @param encoding  the encoding to use, null means platform default
469      * @throws NullPointerException if output is null
470      * @throws IOException if an I/O error occurs
471      * @since 2.3
472      */
473     public static void write( String data, OutputStream output, Charset encoding ) throws IOException
474     {
475         if ( data != null )
476         {
477             output.write( data.getBytes( toCharset( encoding ) ) );
478         }
479     }
480 
481 
482     /**
483      * Gets the contents of an <code>InputStream</code> as a <code>byte[]</code>.
484      * Use this method instead of <code>toByteArray(InputStream)</code>
485      * when <code>InputStream</code> size is known
486      * @param input the <code>InputStream</code> to read from
487      * @param size the size of <code>InputStream</code>
488      * @return the requested byte array
489      * @throws IOException if an I/O error occurs or <code>InputStream</code> size differ from parameter size
490      * @throws IllegalArgumentException if size is less than zero
491      * @since 2.1
492      */
493     public static byte[] toByteArray( InputStream input, int size ) throws IOException
494     {
495         if ( size < 0 )
496         {
497             throw new IllegalArgumentException( "Size must be equal or greater than zero: " + size );
498         }
499 
500         if ( size == 0 )
501         {
502             return new byte[0];
503         }
504 
505         byte[] data = new byte[size];
506         int offset = 0;
507         int readed = input.read( data, offset, size - offset );
508 
509         while ( offset < size && ( readed != EOF ) )
510         {
511             offset += readed;
512             readed = input.read( data, offset, size - offset );
513         }
514 
515         if ( offset != size )
516         {
517             throw new IOException( "Unexpected readed size. current: " + offset + ", excepted: " + size );
518         }
519 
520         return data;
521     }
522     
523     
524     /**
525      * Gets contents of an <code>InputStream</code> as a <code>byte[]</code>.
526      * Use this method instead of <code>toByteArray(InputStream)</code>
527      * when <code>InputStream</code> size is known.
528      * <b>NOTE:</b> the method checks that the length can safely be cast to an int without truncation
529      * before using {@link IOUtils#toByteArray(java.io.InputStream, int)} to read into the byte array.
530      * (Arrays can have no more than Integer.MAX_VALUE entries anyway)
531      *
532      * @param input the <code>InputStream</code> to read from
533      * @param size the size of <code>InputStream</code>
534      * @return the requested byte array
535      * @throws IOException if an I/O error occurs or <code>InputStream</code> size differ from parameter size
536      * @throws IllegalArgumentException if size is less than zero or size is greater than Integer.MAX_VALUE
537      * @see IOUtils#toByteArray(java.io.InputStream, int)
538      * @since 2.1
539      */
540     public static byte[] toByteArray( InputStream input, long size ) throws IOException 
541     {
542 
543       if ( size > Integer.MAX_VALUE ) 
544       {
545           throw new IllegalArgumentException( "Size cannot be greater than Integer max value: " + size );
546       }
547 
548       return toByteArray( input, ( int ) size );
549     }
550     
551     
552     /**
553      * Gets the contents of an <code>InputStream</code> as a list of Strings,
554      * one entry per line, using the specified character encoding.
555      * <p>
556      * This method buffers the input internally, so there is no need to use a
557      * <code>BufferedInputStream</code>.
558      *
559      * @param input  the <code>InputStream</code> to read from, not null
560      * @param encoding  the encoding to use, null means platform default
561      * @return the list of Strings, never null
562      * @throws NullPointerException if the input is null
563      * @throws IOException if an I/O error occurs
564      * @since 2.3
565      */
566     public static List<String> readLines( InputStream input, Charset encoding ) throws IOException 
567     {
568         InputStreamReader reader = new InputStreamReader( input, toCharset( encoding ) );
569         
570         return readLines( reader );
571     }
572     
573     
574     /**
575      * Gets the contents of a <code>Reader</code> as a list of Strings,
576      * one entry per line.
577      * <p>
578      * This method buffers the input internally, so there is no need to use a
579      * <code>BufferedReader</code>.
580      *
581      * @param input  the <code>Reader</code> to read from, not null
582      * @return the list of Strings, never null
583      * @throws NullPointerException if the input is null
584      * @throws IOException if an I/O error occurs
585      * @since 1.1
586      */
587     public static List<String> readLines( Reader input ) throws IOException 
588     {
589         BufferedReader reader = toBufferedReader( input );
590         List<String> list = new ArrayList<String>();
591         String line = reader.readLine();
592         
593         while ( line != null ) 
594         {
595             list.add( line );
596             line = reader.readLine();
597         }
598         
599         return list;
600     }
601 
602     
603     /**
604      * Returns the given reader if it is a {@link BufferedReader}, otherwise creates a BufferedReader from the given
605      * reader.
606      *
607      * @param reader
608      *            the reader to wrap or return (not null)
609      * @return the given reader or a new {@link BufferedReader} for the given reader
610      * @since 2.2
611      * @throws NullPointerException if the input parameter is null
612      */
613     public static BufferedReader toBufferedReader( Reader reader ) 
614     {
615         return reader instanceof BufferedReader ? ( BufferedReader ) reader : new BufferedReader( reader );
616     }
617 }