001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.wicket.util.io; 018 019import java.io.BufferedInputStream; 020import java.io.BufferedReader; 021import java.io.CharArrayWriter; 022import java.io.Closeable; 023import java.io.IOException; 024import java.io.InputStream; 025import java.io.InputStreamReader; 026import java.io.OutputStream; 027import java.io.OutputStreamWriter; 028import java.io.Reader; 029import java.io.StringWriter; 030import java.io.Writer; 031 032import org.slf4j.Logger; 033import org.slf4j.LoggerFactory; 034 035/** 036 * General IO Stream manipulation. 037 * <p> 038 * This class provides static utility methods for input/output operations. 039 * <ul> 040 * <li>closeQuietly - these method closes any kind of closeable resource, e.g. an input/output 041 * stream or reader/writer ignoring nulls and exceptions 042 * <li>toXxx - these methods read data from a stream 043 * <li>write - these methods write data to a stream 044 * <li>copy - these methods copy all the data from one stream to another 045 * <li>contentEquals - these methods compare the content of two streams 046 * </ul> 047 * <p> 048 * The byte-to-char methods and char-to-byte methods involve a conversion step. Two methods are 049 * provided in each case, one that uses the platform default encoding and the other which allows you 050 * to specify an encoding. You are encouraged to always specify an encoding because relying on the 051 * platform default can lead to unexpected results, for example when moving from development to 052 * production. 053 * <p> 054 * All the methods in this class that read a stream are buffered internally. This means that there 055 * is no cause to use a <code>BufferedInputStream</code> or <code>BufferedReader</code>. The default 056 * buffer size of 4K has been show to be efficient in tests. 057 * <p> 058 * Wherever possible, the methods in this class do <em>not</em> flush or close the stream. This is 059 * to avoid making non-portable assumptions about the streams' origin and further use. Thus the 060 * caller is still responsible for closing streams after use. 061 * <p> 062 * Origin of code: Apache Avalon (Excalibur) 063 * 064 * @author Peter Donald 065 * @author Jeff Turner 066 * @author Matthew Hawthorne 067 * @author Stephen Colebourne 068 * @author Gareth Davis 069 */ 070public final class IOUtils 071{ 072 private static final Logger log = LoggerFactory.getLogger(IOUtils.class); 073 074 // NOTE: This class is focused on InputStream, OutputStream, Reader and 075 // Writer. Each method should take at least one of these as a parameter. 076 // NOTE: This class should not depend on any other classes 077 078 /** 079 * The default buffer size to use. 080 */ 081 private static final int DEFAULT_BUFFER_SIZE = 1024 * 4; 082 083 /** 084 * Instances should NOT be constructed in standard programming. 085 */ 086 public IOUtils() 087 { 088 } 089 090 /** 091 * Closes a closeable. Guards against null closables. 092 * 093 * @param closeable 094 * closeable to close 095 * @throws IOException 096 * when close fails 097 */ 098 public static void close(final Closeable closeable) throws IOException 099 { 100 if (closeable != null) 101 { 102 closeable.close(); 103 } 104 } 105 106 /** 107 * Unconditionally close a <code>Closeable</code>. 108 * <p> 109 * closeables can be input or output streams, reader, writers, and much more. 110 * 111 * Equivalent to {@link Closeable#close()}, except any exceptions will be ignored. This is 112 * typically used in finally blocks. 113 * 114 * @param closeable 115 * the Closeable to close, may be null or already closed 116 */ 117 public static void closeQuietly(final Closeable closeable) 118 { 119 try 120 { 121 close(closeable); 122 } 123 catch (IOException e) 124 { 125 log.debug("closing resource failed: " + e.getMessage(), e); 126 } 127 } 128 129 /** 130 * Get the contents of an <code>InputStream</code> as a <code>byte[]</code>. 131 * <p> 132 * This method buffers the input internally, so there is no need to use a 133 * <code>BufferedInputStream</code>. 134 * 135 * @param input 136 * the <code>InputStream</code> to read from 137 * @return the requested byte array 138 * @throws NullPointerException 139 * if the input is null 140 * @throws IOException 141 * if an I/O error occurs 142 */ 143 public static byte[] toByteArray(final InputStream input) throws IOException 144 { 145 ByteArrayOutputStream output = new ByteArrayOutputStream(); 146 copy(input, output); 147 return output.toByteArray(); 148 } 149 150 /** 151 * Get the contents of a <code>Reader</code> as a <code>byte[]</code> using the default 152 * character encoding of the platform. 153 * <p> 154 * This method buffers the input internally, so there is no need to use a 155 * <code>BufferedReader</code>. 156 * 157 * @param input 158 * the <code>Reader</code> to read from 159 * @return the requested byte array 160 * @throws NullPointerException 161 * if the input is null 162 * @throws IOException 163 * if an I/O error occurs 164 */ 165 public static byte[] toByteArray(final Reader input) throws IOException 166 { 167 ByteArrayOutputStream output = new ByteArrayOutputStream(); 168 copy(input, output); 169 return output.toByteArray(); 170 } 171 172 /** 173 * Get the contents of a <code>Reader</code> as a <code>byte[]</code> using the specified 174 * character encoding. 175 * <p> 176 * Character encoding names can be found at <a 177 * href="http://www.iana.org/assignments/character-sets">IANA</a>. 178 * <p> 179 * This method buffers the input internally, so there is no need to use a 180 * <code>BufferedReader</code>. 181 * 182 * @param input 183 * the <code>Reader</code> to read from 184 * @param encoding 185 * the encoding to use, null means platform default 186 * @return the requested byte array 187 * @throws NullPointerException 188 * if the input is null 189 * @throws IOException 190 * if an I/O error occurs 191 * @since 1.1 192 */ 193 public static byte[] toByteArray(final Reader input, final String encoding) throws IOException 194 { 195 ByteArrayOutputStream output = new ByteArrayOutputStream(); 196 copy(input, output, encoding); 197 return output.toByteArray(); 198 } 199 200 /** 201 * Get the contents of an <code>InputStream</code> as a character array using the default 202 * character encoding of the platform. 203 * <p> 204 * This method buffers the input internally, so there is no need to use a 205 * <code>BufferedInputStream</code>. 206 * 207 * @param is 208 * the <code>InputStream</code> to read from 209 * @return the requested character array 210 * @throws NullPointerException 211 * if the input is null 212 * @throws IOException 213 * if an I/O error occurs 214 */ 215 public static char[] toCharArray(final InputStream is) throws IOException 216 { 217 CharArrayWriter output = new CharArrayWriter(); 218 copy(is, output); 219 return output.toCharArray(); 220 } 221 222 /** 223 * Get the contents of an <code>InputStream</code> as a character array using the specified 224 * character encoding. 225 * <p> 226 * Character encoding names can be found at <a 227 * href="http://www.iana.org/assignments/character-sets">IANA</a>. 228 * <p> 229 * This method buffers the input internally, so there is no need to use a 230 * <code>BufferedInputStream</code>. 231 * 232 * @param is 233 * the <code>InputStream</code> to read from 234 * @param encoding 235 * the encoding to use, null means platform default 236 * @return the requested character array 237 * @throws NullPointerException 238 * if the input is null 239 * @throws IOException 240 * if an I/O error occurs 241 */ 242 public static char[] toCharArray(final InputStream is, final String encoding) 243 throws IOException 244 { 245 CharArrayWriter output = new CharArrayWriter(); 246 copy(is, output, encoding); 247 return output.toCharArray(); 248 } 249 250 /** 251 * Get the contents of a <code>Reader</code> as a character array. 252 * <p> 253 * This method buffers the input internally, so there is no need to use a 254 * <code>BufferedReader</code>. 255 * 256 * @param input 257 * the <code>Reader</code> to read from 258 * @return the requested character array 259 * @throws NullPointerException 260 * if the input is null 261 * @throws IOException 262 * if an I/O error occurs 263 */ 264 public static char[] toCharArray(final Reader input) throws IOException 265 { 266 CharArrayWriter sw = new CharArrayWriter(); 267 copy(input, sw); 268 return sw.toCharArray(); 269 } 270 271 /** 272 * Get the contents of an <code>InputStream</code> as a String using the default character 273 * encoding of the platform. 274 * <p> 275 * This method buffers the input internally, so there is no need to use a 276 * <code>BufferedInputStream</code>. 277 * 278 * @param input 279 * the <code>InputStream</code> to read from 280 * @return the requested String 281 * @throws NullPointerException 282 * if the input is null 283 * @throws IOException 284 * if an I/O error occurs 285 */ 286 public static String toString(final InputStream input) throws IOException 287 { 288 StringWriter sw = new StringWriter(); 289 copy(input, sw); 290 return sw.toString(); 291 } 292 293 /** 294 * Get the contents of an <code>InputStream</code> as a String using the specified character 295 * encoding. 296 * <p> 297 * Character encoding names can be found at <a 298 * href="http://www.iana.org/assignments/character-sets">IANA</a>. 299 * <p> 300 * This method buffers the input internally, so there is no need to use a 301 * <code>BufferedInputStream</code>. 302 * 303 * @param input 304 * the <code>InputStream</code> to read from 305 * @param encoding 306 * the encoding to use, null means platform default 307 * @return the requested String 308 * @throws NullPointerException 309 * if the input is null 310 * @throws IOException 311 * if an I/O error occurs 312 */ 313 public static String toString(final InputStream input, final String encoding) 314 throws IOException 315 { 316 StringWriter sw = new StringWriter(); 317 copy(input, sw, encoding); 318 return sw.toString(); 319 } 320 321 /** 322 * Get the contents of a <code>Reader</code> as a String. 323 * <p> 324 * This method buffers the input internally, so there is no need to use a 325 * <code>BufferedReader</code>. 326 * 327 * @param input 328 * the <code>Reader</code> to read from 329 * @return the requested String 330 * @throws NullPointerException 331 * if the input is null 332 * @throws IOException 333 * if an I/O error occurs 334 */ 335 public static String toString(final Reader input) throws IOException 336 { 337 StringWriter sw = new StringWriter(); 338 copy(input, sw); 339 return sw.toString(); 340 } 341 342 /** 343 * Writes bytes from a <code>byte[]</code> to an <code>OutputStream</code>. 344 * 345 * @param data 346 * the byte array to write, do not modify during output, null ignored 347 * @param output 348 * the <code>OutputStream</code> to write to 349 * @throws NullPointerException 350 * if output is null 351 * @throws IOException 352 * if an I/O error occurs 353 * @since 1.1 354 */ 355 public static void write(final byte[] data, final OutputStream output) throws IOException 356 { 357 if (data != null) 358 { 359 output.write(data); 360 } 361 } 362 363 /** 364 * Writes bytes from a <code>byte[]</code> to chars on a <code>Writer</code> using the default 365 * character encoding of the platform. 366 * <p> 367 * This method uses {@link String#String(byte[])}. 368 * 369 * @param data 370 * the byte array to write, do not modify during output, null ignored 371 * @param output 372 * the <code>Writer</code> to write to 373 * @throws NullPointerException 374 * if output is null 375 * @throws IOException 376 * if an I/O error occurs 377 * @since 1.1 378 */ 379 public static void write(final byte[] data, final Writer output) throws IOException 380 { 381 if (data != null) 382 { 383 output.write(new String(data)); 384 } 385 } 386 387 /** 388 * Writes bytes from a <code>byte[]</code> to chars on a <code>Writer</code> using the specified 389 * character encoding. 390 * <p> 391 * Character encoding names can be found at <a 392 * href="http://www.iana.org/assignments/character-sets">IANA</a>. 393 * <p> 394 * This method uses {@link String#String(byte[], String)}. 395 * 396 * @param data 397 * the byte array to write, do not modify during output, null ignored 398 * @param output 399 * the <code>Writer</code> to write to 400 * @param encoding 401 * the encoding to use, null means platform default 402 * @throws NullPointerException 403 * if output is null 404 * @throws IOException 405 * if an I/O error occurs 406 * @since 1.1 407 */ 408 public static void write(final byte[] data, final Writer output, final String encoding) 409 throws IOException 410 { 411 if (data != null) 412 { 413 if (encoding == null) 414 { 415 write(data, output); 416 } 417 else 418 { 419 output.write(new String(data, encoding)); 420 } 421 } 422 } 423 424 /** 425 * Writes chars from a <code>char[]</code> to a <code>Writer</code> using the default character 426 * encoding of the platform. 427 * 428 * @param data 429 * the char array to write, do not modify during output, null ignored 430 * @param output 431 * the <code>Writer</code> to write to 432 * @throws NullPointerException 433 * if output is null 434 * @throws IOException 435 * if an I/O error occurs 436 * @since 1.1 437 */ 438 public static void write(final char[] data, final Writer output) throws IOException 439 { 440 if (data != null) 441 { 442 output.write(data); 443 } 444 } 445 446 /** 447 * Writes chars from a <code>char[]</code> to bytes on an <code>OutputStream</code>. 448 * <p> 449 * This method uses {@link String#String(char[])} and {@link String#getBytes()}. 450 * 451 * @param data 452 * the char array to write, do not modify during output, null ignored 453 * @param output 454 * the <code>OutputStream</code> to write to 455 * @throws NullPointerException 456 * if output is null 457 * @throws IOException 458 * if an I/O error occurs 459 * @since 1.1 460 */ 461 public static void write(final char[] data, final OutputStream output) throws IOException 462 { 463 if (data != null) 464 { 465 output.write(new String(data).getBytes()); 466 } 467 } 468 469 /** 470 * Writes chars from a <code>char[]</code> to bytes on an <code>OutputStream</code> using the 471 * specified character encoding. 472 * <p> 473 * Character encoding names can be found at <a 474 * href="http://www.iana.org/assignments/character-sets">IANA</a>. 475 * <p> 476 * This method uses {@link String#String(char[])} and {@link String#getBytes(String)}. 477 * 478 * @param data 479 * the char array to write, do not modify during output, null ignored 480 * @param output 481 * the <code>OutputStream</code> to write to 482 * @param encoding 483 * the encoding to use, null means platform default 484 * @throws NullPointerException 485 * if output is null 486 * @throws IOException 487 * if an I/O error occurs 488 * @since 1.1 489 */ 490 public static void write(final char[] data, final OutputStream output, final String encoding) 491 throws IOException 492 { 493 if (data != null) 494 { 495 if (encoding == null) 496 { 497 write(data, output); 498 } 499 else 500 { 501 output.write(new String(data).getBytes(encoding)); 502 } 503 } 504 } 505 506 /** 507 * Writes chars from a <code>String</code> to a <code>Writer</code>. 508 * 509 * @param data 510 * the <code>String</code> to write, null ignored 511 * @param output 512 * the <code>Writer</code> to write to 513 * @throws NullPointerException 514 * if output is null 515 * @throws IOException 516 * if an I/O error occurs 517 * @since 1.1 518 */ 519 public static void write(final String data, final Writer output) throws IOException 520 { 521 if (data != null) 522 { 523 output.write(data); 524 } 525 } 526 527 /** 528 * Writes chars from a <code>String</code> to bytes on an <code>OutputStream</code> using the 529 * default character encoding of the platform. 530 * <p> 531 * This method uses {@link String#getBytes()}. 532 * 533 * @param data 534 * the <code>String</code> to write, null ignored 535 * @param output 536 * the <code>OutputStream</code> to write to 537 * @throws NullPointerException 538 * if output is null 539 * @throws IOException 540 * if an I/O error occurs 541 * @since 1.1 542 */ 543 public static void write(final String data, final OutputStream output) throws IOException 544 { 545 if (data != null) 546 { 547 output.write(data.getBytes()); 548 } 549 } 550 551 /** 552 * Writes chars from a <code>String</code> to bytes on an <code>OutputStream</code> using the 553 * specified character encoding. 554 * <p> 555 * Character encoding names can be found at <a 556 * href="http://www.iana.org/assignments/character-sets">IANA</a>. 557 * <p> 558 * This method uses {@link String#getBytes(String)}. 559 * 560 * @param data 561 * the <code>String</code> to write, null ignored 562 * @param output 563 * the <code>OutputStream</code> to write to 564 * @param encoding 565 * the encoding to use, null means platform default 566 * @throws NullPointerException 567 * if output is null 568 * @throws IOException 569 * if an I/O error occurs 570 * @since 1.1 571 */ 572 public static void write(final String data, final OutputStream output, final String encoding) 573 throws IOException 574 { 575 if (data != null) 576 { 577 if (encoding == null) 578 { 579 write(data, output); 580 } 581 else 582 { 583 output.write(data.getBytes(encoding)); 584 } 585 } 586 } 587 588 /** 589 * Writes chars from a <code>AppendingStringBuffer</code> to a <code>Writer</code>. 590 * 591 * @param data 592 * the <code>AppendingStringBuffer</code> to write, null ignored 593 * @param output 594 * the <code>Writer</code> to write to 595 * @throws NullPointerException 596 * if output is null 597 * @throws IOException 598 * if an I/O error occurs 599 * @since 1.1 600 */ 601 public static void write(final StringBuilder data, final Writer output) throws IOException 602 { 603 if (data != null) 604 { 605 output.write(data.toString()); 606 } 607 } 608 609 /** 610 * Writes chars from a <code>AppendingStringBuffer</code> to bytes on an 611 * <code>OutputStream</code> using the default character encoding of the platform. 612 * <p> 613 * This method uses {@link String#getBytes()}. 614 * 615 * @param data 616 * the <code>AppendingStringBuffer</code> to write, null ignored 617 * @param output 618 * the <code>OutputStream</code> to write to 619 * @throws NullPointerException 620 * if output is null 621 * @throws IOException 622 * if an I/O error occurs 623 * @since 1.1 624 */ 625 public static void write(final StringBuilder data, final OutputStream output) 626 throws IOException 627 { 628 if (data != null) 629 { 630 output.write(data.toString().getBytes()); 631 } 632 } 633 634 /** 635 * Writes chars from a <code>AppendingStringBuffer</code> to bytes on an 636 * <code>OutputStream</code> using the specified character encoding. 637 * <p> 638 * Character encoding names can be found at <a 639 * href="http://www.iana.org/assignments/character-sets">IANA</a>. 640 * <p> 641 * This method uses {@link String#getBytes(String)}. 642 * 643 * @param data 644 * the <code>AppendingStringBuffer</code> to write, null ignored 645 * @param output 646 * the <code>OutputStream</code> to write to 647 * @param encoding 648 * the encoding to use, null means platform default 649 * @throws NullPointerException 650 * if output is null 651 * @throws IOException 652 * if an I/O error occurs 653 * @since 1.1 654 */ 655 public static void write(final StringBuilder data, final OutputStream output, 656 final String encoding) throws IOException 657 { 658 if (data != null) 659 { 660 if (encoding == null) 661 { 662 write(data, output); 663 } 664 else 665 { 666 output.write(data.toString().getBytes(encoding)); 667 } 668 } 669 } 670 671 /** 672 * Copy bytes from an <code>InputStream</code> to an <code>OutputStream</code>. 673 * <p> 674 * This method buffers the input internally, so there is no need to use a 675 * <code>BufferedInputStream</code>. 676 * 677 * @param input 678 * the <code>InputStream</code> to read from 679 * @param output 680 * the <code>OutputStream</code> to write to 681 * @return the number of bytes copied 682 * @throws NullPointerException 683 * if the input or output is null 684 * @throws IOException 685 * if an I/O error occurs 686 * @since 1.1 687 */ 688 public static int copy(final InputStream input, final OutputStream output) throws IOException 689 { 690 byte[] buffer = new byte[DEFAULT_BUFFER_SIZE]; 691 int count = 0; 692 int n = 0; 693 while (-1 != (n = input.read(buffer))) 694 { 695 output.write(buffer, 0, n); 696 count += n; 697 } 698 return count; 699 } 700 701 /** 702 * Copy bytes from an <code>InputStream</code> to chars on a <code>Writer</code> using the 703 * default character encoding of the platform. 704 * <p> 705 * This method buffers the input internally, so there is no need to use a 706 * <code>BufferedInputStream</code>. 707 * <p> 708 * This method uses {@link InputStreamReader}. 709 * 710 * @param input 711 * the <code>InputStream</code> to read from 712 * @param output 713 * the <code>Writer</code> to write to 714 * @throws NullPointerException 715 * if the input or output is null 716 * @throws IOException 717 * if an I/O error occurs 718 * @since 1.1 719 */ 720 public static void copy(final InputStream input, final Writer output) throws IOException 721 { 722 InputStreamReader in = new InputStreamReader(input); 723 copy(in, output); 724 } 725 726 /** 727 * Copy bytes from an <code>InputStream</code> to chars on a <code>Writer</code> using the 728 * specified character encoding. 729 * <p> 730 * This method buffers the input internally, so there is no need to use a 731 * <code>BufferedInputStream</code>. 732 * <p> 733 * Character encoding names can be found at <a 734 * href="http://www.iana.org/assignments/character-sets">IANA</a>. 735 * <p> 736 * This method uses {@link InputStreamReader}. 737 * 738 * @param input 739 * the <code>InputStream</code> to read from 740 * @param output 741 * the <code>Writer</code> to write to 742 * @param encoding 743 * the encoding to use, null means platform default 744 * @throws NullPointerException 745 * if the input or output is null 746 * @throws IOException 747 * if an I/O error occurs 748 * @since 1.1 749 */ 750 public static void copy(final InputStream input, final Writer output, final String encoding) 751 throws IOException 752 { 753 if (encoding == null) 754 { 755 copy(input, output); 756 } 757 else 758 { 759 InputStreamReader in = new InputStreamReader(input, encoding); 760 copy(in, output); 761 } 762 } 763 764 /** 765 * Copy chars from a <code>Reader</code> to a <code>Writer</code>. 766 * <p> 767 * This method buffers the input internally, so there is no need to use a 768 * <code>BufferedReader</code>. 769 * 770 * @param input 771 * the <code>Reader</code> to read from 772 * @param output 773 * the <code>Writer</code> to write to 774 * @return the number of characters copied 775 * @throws NullPointerException 776 * if the input or output is null 777 * @throws IOException 778 * if an I/O error occurs 779 * @since 1.1 780 */ 781 public static int copy(final Reader input, final Writer output) throws IOException 782 { 783 char[] buffer = new char[DEFAULT_BUFFER_SIZE]; 784 int count = 0; 785 int n = 0; 786 while (-1 != (n = input.read(buffer))) 787 { 788 output.write(buffer, 0, n); 789 count += n; 790 } 791 return count; 792 } 793 794 /** 795 * Copy chars from a <code>Reader</code> to bytes on an <code>OutputStream</code> using the 796 * default character encoding of the platform, and calling flush. 797 * <p> 798 * This method buffers the input internally, so there is no need to use a 799 * <code>BufferedReader</code>. 800 * <p> 801 * Due to the implementation of OutputStreamWriter, this method performs a flush. 802 * <p> 803 * This method uses {@link OutputStreamWriter}. 804 * 805 * @param input 806 * the <code>Reader</code> to read from 807 * @param output 808 * the <code>OutputStream</code> to write to 809 * @throws NullPointerException 810 * if the input or output is null 811 * @throws IOException 812 * if an I/O error occurs 813 * @since 1.1 814 */ 815 public static void copy(final Reader input, final OutputStream output) throws IOException 816 { 817 OutputStreamWriter out = new OutputStreamWriter(output); 818 copy(input, out); 819 out.flush(); 820 } 821 822 /** 823 * Copy chars from a <code>Reader</code> to bytes on an <code>OutputStream</code> using the 824 * specified character encoding, and calling flush. 825 * <p> 826 * This method buffers the input internally, so there is no need to use a 827 * <code>BufferedReader</code>. 828 * <p> 829 * Character encoding names can be found at <a 830 * href="http://www.iana.org/assignments/character-sets">IANA</a>. 831 * <p> 832 * Due to the implementation of OutputStreamWriter, this method performs a flush. 833 * <p> 834 * This method uses {@link OutputStreamWriter}. 835 * 836 * @param input 837 * the <code>Reader</code> to read from 838 * @param output 839 * the <code>OutputStream</code> to write to 840 * @param encoding 841 * the encoding to use, null means platform default 842 * @throws NullPointerException 843 * if the input or output is null 844 * @throws IOException 845 * if an I/O error occurs 846 * @since 1.1 847 */ 848 public static void copy(final Reader input, final OutputStream output, final String encoding) 849 throws IOException 850 { 851 if (encoding == null) 852 { 853 copy(input, output); 854 } 855 else 856 { 857 OutputStreamWriter out = new OutputStreamWriter(output, encoding); 858 copy(input, out); 859 out.flush(); 860 } 861 } 862 863 /** 864 * Compare the contents of two Streams to determine if they are equal or not. 865 * <p> 866 * This method buffers the input internally using <code>BufferedInputStream</code> if they are 867 * not already buffered. 868 * 869 * @param input1 870 * the first stream 871 * @param input2 872 * the second stream 873 * @return true if the content of the streams are equal or they both don't exist, false 874 * otherwise 875 * @throws NullPointerException 876 * if either input is null 877 * @throws IOException 878 * if an I/O error occurs 879 */ 880 public static boolean contentEquals(InputStream input1, InputStream input2) throws IOException 881 { 882 if (!(input1 instanceof BufferedInputStream)) 883 { 884 input1 = new BufferedInputStream(input1); 885 } 886 if (!(input2 instanceof BufferedInputStream)) 887 { 888 input2 = new BufferedInputStream(input2); 889 } 890 891 int ch = input1.read(); 892 while (-1 != ch) 893 { 894 int ch2 = input2.read(); 895 if (ch != ch2) 896 { 897 return false; 898 } 899 ch = input1.read(); 900 } 901 902 int ch2 = input2.read(); 903 return (ch2 == -1); 904 } 905 906 /** 907 * Compare the contents of two Readers to determine if they are equal or not. 908 * <p> 909 * This method buffers the input internally using <code>BufferedReader</code> if they are not 910 * already buffered. 911 * 912 * @param input1 913 * the first reader 914 * @param input2 915 * the second reader 916 * @return true if the content of the readers are equal or they both don't exist, false 917 * otherwise 918 * @throws NullPointerException 919 * if either input is null 920 * @throws IOException 921 * if an I/O error occurs 922 * @since 1.1 923 */ 924 public static boolean contentEquals(Reader input1, Reader input2) throws IOException 925 { 926 if (!(input1 instanceof BufferedReader)) 927 { 928 input1 = new BufferedReader(input1); 929 } 930 if (!(input2 instanceof BufferedReader)) 931 { 932 input2 = new BufferedReader(input2); 933 } 934 935 int ch = input1.read(); 936 while (-1 != ch) 937 { 938 int ch2 = input2.read(); 939 if (ch != ch2) 940 { 941 return false; 942 } 943 ch = input1.read(); 944 } 945 946 int ch2 = input2.read(); 947 return (ch2 == -1); 948 } 949}