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