001/* 002 * Copyright (C) 2007 The Guava Authors 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package com.google.common.io; 018 019import static com.google.common.base.Preconditions.checkArgument; 020import static com.google.common.base.Preconditions.checkNotNull; 021import static com.google.common.base.Preconditions.checkPositionIndex; 022 023import com.google.common.annotations.Beta; 024import com.google.common.base.Function; 025import com.google.common.collect.Iterables; 026import com.google.common.hash.HashCode; 027import com.google.common.hash.HashFunction; 028 029import java.io.ByteArrayInputStream; 030import java.io.ByteArrayOutputStream; 031import java.io.DataInput; 032import java.io.DataInputStream; 033import java.io.DataOutput; 034import java.io.DataOutputStream; 035import java.io.EOFException; 036import java.io.FilterInputStream; 037import java.io.IOException; 038import java.io.InputStream; 039import java.io.OutputStream; 040import java.nio.ByteBuffer; 041import java.nio.channels.ReadableByteChannel; 042import java.nio.channels.WritableByteChannel; 043import java.util.Arrays; 044 045/** 046 * Provides utility methods for working with byte arrays and I/O streams. 047 * 048 * @author Chris Nokleberg 049 * @author Colin Decker 050 * @since 1.0 051 */ 052@Beta 053public final class ByteStreams { 054 private static final int BUF_SIZE = 0x1000; // 4K 055 056 private ByteStreams() {} 057 058 /** 059 * Returns a factory that will supply instances of 060 * {@link ByteArrayInputStream} that read from the given byte array. 061 * 062 * @param b the input buffer 063 * @return the factory 064 * @deprecated Use {@link ByteSource#wrap(byte[])} instead. This method is 065 * scheduled for removal in Guava 18.0. 066 */ 067 @Deprecated 068 public static InputSupplier<ByteArrayInputStream> newInputStreamSupplier( 069 byte[] b) { 070 return asInputSupplier(ByteSource.wrap(b)); 071 } 072 073 /** 074 * Returns a factory that will supply instances of 075 * {@link ByteArrayInputStream} that read from the given byte array. 076 * 077 * @param b the input buffer 078 * @param off the offset in the buffer of the first byte to read 079 * @param len the maximum number of bytes to read from the buffer 080 * @return the factory 081 * @deprecated Use {@code ByteSource.wrap(b).slice(off, len)} instead. This 082 * method is scheduled for removal in Guava 18.0. 083 */ 084 @Deprecated 085 public static InputSupplier<ByteArrayInputStream> newInputStreamSupplier( 086 final byte[] b, final int off, final int len) { 087 return asInputSupplier(ByteSource.wrap(b).slice(off, len)); 088 } 089 090 /** 091 * Writes a byte array to an output stream from the given supplier. 092 * 093 * @param from the bytes to write 094 * @param to the output supplier 095 * @throws IOException if an I/O error occurs 096 * @deprecated Use {@link ByteSink#write(byte[])} instead. This method is 097 * scheduled for removal in Guava 18.0. 098 */ 099 @Deprecated 100 public static void write(byte[] from, 101 OutputSupplier<? extends OutputStream> to) throws IOException { 102 asByteSink(to).write(from); 103 } 104 105 /** 106 * Opens input and output streams from the given suppliers, copies all 107 * bytes from the input to the output, and closes the streams. 108 * 109 * @param from the input factory 110 * @param to the output factory 111 * @return the number of bytes copied 112 * @throws IOException if an I/O error occurs 113 * @deprecated Use {@link ByteSource#copyTo(ByteSink)} instead. This method 114 * is scheduled for removal in Guava 18.0. 115 */ 116 @Deprecated 117 public static long copy(InputSupplier<? extends InputStream> from, 118 OutputSupplier<? extends OutputStream> to) throws IOException { 119 return asByteSource(from).copyTo(asByteSink(to)); 120 } 121 122 /** 123 * Opens an input stream from the supplier, copies all bytes from the 124 * input to the output, and closes the input stream. Does not close 125 * or flush the output stream. 126 * 127 * @param from the input factory 128 * @param to the output stream to write to 129 * @return the number of bytes copied 130 * @throws IOException if an I/O error occurs 131 * @deprecated Use {@link ByteSource#copyTo(OutputStream)} instead. This 132 * method is scheduled for removal in Guava 18.0. 133 */ 134 @Deprecated 135 public static long copy(InputSupplier<? extends InputStream> from, 136 OutputStream to) throws IOException { 137 return asByteSource(from).copyTo(to); 138 } 139 140 /** 141 * Opens an output stream from the supplier, copies all bytes from the input 142 * to the output, and closes the output stream. Does not close or flush the 143 * input stream. 144 * 145 * @param from the input stream to read from 146 * @param to the output factory 147 * @return the number of bytes copied 148 * @throws IOException if an I/O error occurs 149 * @since 10.0 150 * @deprecated Use {@link ByteSink#writeFrom(InputStream)} instead. This 151 * method is scheduled for removal in Guava 18.0. 152 */ 153 @Deprecated 154 public static long copy(InputStream from, 155 OutputSupplier<? extends OutputStream> to) throws IOException { 156 return asByteSink(to).writeFrom(from); 157 } 158 159 /** 160 * Copies all bytes from the input stream to the output stream. 161 * Does not close or flush either stream. 162 * 163 * @param from the input stream to read from 164 * @param to the output stream to write to 165 * @return the number of bytes copied 166 * @throws IOException if an I/O error occurs 167 */ 168 public static long copy(InputStream from, OutputStream to) 169 throws IOException { 170 checkNotNull(from); 171 checkNotNull(to); 172 byte[] buf = new byte[BUF_SIZE]; 173 long total = 0; 174 while (true) { 175 int r = from.read(buf); 176 if (r == -1) { 177 break; 178 } 179 to.write(buf, 0, r); 180 total += r; 181 } 182 return total; 183 } 184 185 /** 186 * Copies all bytes from the readable channel to the writable channel. 187 * Does not close or flush either channel. 188 * 189 * @param from the readable channel to read from 190 * @param to the writable channel to write to 191 * @return the number of bytes copied 192 * @throws IOException if an I/O error occurs 193 */ 194 public static long copy(ReadableByteChannel from, 195 WritableByteChannel to) throws IOException { 196 checkNotNull(from); 197 checkNotNull(to); 198 ByteBuffer buf = ByteBuffer.allocate(BUF_SIZE); 199 long total = 0; 200 while (from.read(buf) != -1) { 201 buf.flip(); 202 while (buf.hasRemaining()) { 203 total += to.write(buf); 204 } 205 buf.clear(); 206 } 207 return total; 208 } 209 210 /** 211 * Reads all bytes from an input stream into a byte array. 212 * Does not close the stream. 213 * 214 * @param in the input stream to read from 215 * @return a byte array containing all the bytes from the stream 216 * @throws IOException if an I/O error occurs 217 */ 218 public static byte[] toByteArray(InputStream in) throws IOException { 219 ByteArrayOutputStream out = new ByteArrayOutputStream(); 220 copy(in, out); 221 return out.toByteArray(); 222 } 223 224 /** 225 * Reads all bytes from an input stream into a byte array. The given 226 * expected size is used to create an initial byte array, but if the actual 227 * number of bytes read from the stream differs, the correct result will be 228 * returned anyway. 229 */ 230 static byte[] toByteArray( 231 InputStream in, int expectedSize) throws IOException { 232 byte[] bytes = new byte[expectedSize]; 233 int remaining = expectedSize; 234 235 while (remaining > 0) { 236 int off = expectedSize - remaining; 237 int read = in.read(bytes, off, remaining); 238 if (read == -1) { 239 // end of stream before reading expectedSize bytes 240 // just return the bytes read so far 241 return Arrays.copyOf(bytes, off); 242 } 243 remaining -= read; 244 } 245 246 // bytes is now full 247 int b = in.read(); 248 if (b == -1) { 249 return bytes; 250 } 251 252 // the stream was longer, so read the rest normally 253 FastByteArrayOutputStream out = new FastByteArrayOutputStream(); 254 out.write(b); // write the byte we read when testing for end of stream 255 copy(in, out); 256 257 byte[] result = new byte[bytes.length + out.size()]; 258 System.arraycopy(bytes, 0, result, 0, bytes.length); 259 out.writeTo(result, bytes.length); 260 return result; 261 } 262 263 /** 264 * BAOS that provides limited access to its internal byte array. 265 */ 266 private static final class FastByteArrayOutputStream 267 extends ByteArrayOutputStream { 268 /** 269 * Writes the contents of the internal buffer to the given array starting 270 * at the given offset. Assumes the array has space to hold count bytes. 271 */ 272 void writeTo(byte[] b, int off) { 273 System.arraycopy(buf, 0, b, off, count); 274 } 275 } 276 277 /** 278 * Returns the data from a {@link InputStream} factory as a byte array. 279 * 280 * @param supplier the factory 281 * @throws IOException if an I/O error occurs 282 * @deprecated Use {@link ByteSource#read()} instead. This method is 283 * scheduled for removal in Guava 18.0. 284 */ 285 @Deprecated 286 public static byte[] toByteArray( 287 InputSupplier<? extends InputStream> supplier) throws IOException { 288 return asByteSource(supplier).read(); 289 } 290 291 /** 292 * Returns a new {@link ByteArrayDataInput} instance to read from the {@code 293 * bytes} array from the beginning. 294 */ 295 public static ByteArrayDataInput newDataInput(byte[] bytes) { 296 return new ByteArrayDataInputStream(bytes); 297 } 298 299 /** 300 * Returns a new {@link ByteArrayDataInput} instance to read from the {@code 301 * bytes} array, starting at the given position. 302 * 303 * @throws IndexOutOfBoundsException if {@code start} is negative or greater 304 * than the length of the array 305 */ 306 public static ByteArrayDataInput newDataInput(byte[] bytes, int start) { 307 checkPositionIndex(start, bytes.length); 308 return new ByteArrayDataInputStream(bytes, start); 309 } 310 311 private static class ByteArrayDataInputStream implements ByteArrayDataInput { 312 final DataInput input; 313 314 ByteArrayDataInputStream(byte[] bytes) { 315 this.input = new DataInputStream(new ByteArrayInputStream(bytes)); 316 } 317 318 ByteArrayDataInputStream(byte[] bytes, int start) { 319 this.input = new DataInputStream( 320 new ByteArrayInputStream(bytes, start, bytes.length - start)); 321 } 322 323 @Override public void readFully(byte b[]) { 324 try { 325 input.readFully(b); 326 } catch (IOException e) { 327 throw new IllegalStateException(e); 328 } 329 } 330 331 @Override public void readFully(byte b[], int off, int len) { 332 try { 333 input.readFully(b, off, len); 334 } catch (IOException e) { 335 throw new IllegalStateException(e); 336 } 337 } 338 339 @Override public int skipBytes(int n) { 340 try { 341 return input.skipBytes(n); 342 } catch (IOException e) { 343 throw new IllegalStateException(e); 344 } 345 } 346 347 @Override public boolean readBoolean() { 348 try { 349 return input.readBoolean(); 350 } catch (IOException e) { 351 throw new IllegalStateException(e); 352 } 353 } 354 355 @Override public byte readByte() { 356 try { 357 return input.readByte(); 358 } catch (EOFException e) { 359 throw new IllegalStateException(e); 360 } catch (IOException impossible) { 361 throw new AssertionError(impossible); 362 } 363 } 364 365 @Override public int readUnsignedByte() { 366 try { 367 return input.readUnsignedByte(); 368 } catch (IOException e) { 369 throw new IllegalStateException(e); 370 } 371 } 372 373 @Override public short readShort() { 374 try { 375 return input.readShort(); 376 } catch (IOException e) { 377 throw new IllegalStateException(e); 378 } 379 } 380 381 @Override public int readUnsignedShort() { 382 try { 383 return input.readUnsignedShort(); 384 } catch (IOException e) { 385 throw new IllegalStateException(e); 386 } 387 } 388 389 @Override public char readChar() { 390 try { 391 return input.readChar(); 392 } catch (IOException e) { 393 throw new IllegalStateException(e); 394 } 395 } 396 397 @Override public int readInt() { 398 try { 399 return input.readInt(); 400 } catch (IOException e) { 401 throw new IllegalStateException(e); 402 } 403 } 404 405 @Override public long readLong() { 406 try { 407 return input.readLong(); 408 } catch (IOException e) { 409 throw new IllegalStateException(e); 410 } 411 } 412 413 @Override public float readFloat() { 414 try { 415 return input.readFloat(); 416 } catch (IOException e) { 417 throw new IllegalStateException(e); 418 } 419 } 420 421 @Override public double readDouble() { 422 try { 423 return input.readDouble(); 424 } catch (IOException e) { 425 throw new IllegalStateException(e); 426 } 427 } 428 429 @Override public String readLine() { 430 try { 431 return input.readLine(); 432 } catch (IOException e) { 433 throw new IllegalStateException(e); 434 } 435 } 436 437 @Override public String readUTF() { 438 try { 439 return input.readUTF(); 440 } catch (IOException e) { 441 throw new IllegalStateException(e); 442 } 443 } 444 } 445 446 /** 447 * Returns a new {@link ByteArrayDataOutput} instance with a default size. 448 */ 449 public static ByteArrayDataOutput newDataOutput() { 450 return new ByteArrayDataOutputStream(); 451 } 452 453 /** 454 * Returns a new {@link ByteArrayDataOutput} instance sized to hold 455 * {@code size} bytes before resizing. 456 * 457 * @throws IllegalArgumentException if {@code size} is negative 458 */ 459 public static ByteArrayDataOutput newDataOutput(int size) { 460 checkArgument(size >= 0, "Invalid size: %s", size); 461 return new ByteArrayDataOutputStream(size); 462 } 463 464 @SuppressWarnings("deprecation") // for writeBytes 465 private static class ByteArrayDataOutputStream 466 implements ByteArrayDataOutput { 467 468 final DataOutput output; 469 final ByteArrayOutputStream byteArrayOutputSteam; 470 471 ByteArrayDataOutputStream() { 472 this(new ByteArrayOutputStream()); 473 } 474 475 ByteArrayDataOutputStream(int size) { 476 this(new ByteArrayOutputStream(size)); 477 } 478 479 ByteArrayDataOutputStream(ByteArrayOutputStream byteArrayOutputSteam) { 480 this.byteArrayOutputSteam = byteArrayOutputSteam; 481 output = new DataOutputStream(byteArrayOutputSteam); 482 } 483 484 @Override public void write(int b) { 485 try { 486 output.write(b); 487 } catch (IOException impossible) { 488 throw new AssertionError(impossible); 489 } 490 } 491 492 @Override public void write(byte[] b) { 493 try { 494 output.write(b); 495 } catch (IOException impossible) { 496 throw new AssertionError(impossible); 497 } 498 } 499 500 @Override public void write(byte[] b, int off, int len) { 501 try { 502 output.write(b, off, len); 503 } catch (IOException impossible) { 504 throw new AssertionError(impossible); 505 } 506 } 507 508 @Override public void writeBoolean(boolean v) { 509 try { 510 output.writeBoolean(v); 511 } catch (IOException impossible) { 512 throw new AssertionError(impossible); 513 } 514 } 515 516 @Override public void writeByte(int v) { 517 try { 518 output.writeByte(v); 519 } catch (IOException impossible) { 520 throw new AssertionError(impossible); 521 } 522 } 523 524 @Override public void writeBytes(String s) { 525 try { 526 output.writeBytes(s); 527 } catch (IOException impossible) { 528 throw new AssertionError(impossible); 529 } 530 } 531 532 @Override public void writeChar(int v) { 533 try { 534 output.writeChar(v); 535 } catch (IOException impossible) { 536 throw new AssertionError(impossible); 537 } 538 } 539 540 @Override public void writeChars(String s) { 541 try { 542 output.writeChars(s); 543 } catch (IOException impossible) { 544 throw new AssertionError(impossible); 545 } 546 } 547 548 @Override public void writeDouble(double v) { 549 try { 550 output.writeDouble(v); 551 } catch (IOException impossible) { 552 throw new AssertionError(impossible); 553 } 554 } 555 556 @Override public void writeFloat(float v) { 557 try { 558 output.writeFloat(v); 559 } catch (IOException impossible) { 560 throw new AssertionError(impossible); 561 } 562 } 563 564 @Override public void writeInt(int v) { 565 try { 566 output.writeInt(v); 567 } catch (IOException impossible) { 568 throw new AssertionError(impossible); 569 } 570 } 571 572 @Override public void writeLong(long v) { 573 try { 574 output.writeLong(v); 575 } catch (IOException impossible) { 576 throw new AssertionError(impossible); 577 } 578 } 579 580 @Override public void writeShort(int v) { 581 try { 582 output.writeShort(v); 583 } catch (IOException impossible) { 584 throw new AssertionError(impossible); 585 } 586 } 587 588 @Override public void writeUTF(String s) { 589 try { 590 output.writeUTF(s); 591 } catch (IOException impossible) { 592 throw new AssertionError(impossible); 593 } 594 } 595 596 @Override public byte[] toByteArray() { 597 return byteArrayOutputSteam.toByteArray(); 598 } 599 } 600 601 private static final OutputStream NULL_OUTPUT_STREAM = 602 new OutputStream() { 603 /** Discards the specified byte. */ 604 @Override public void write(int b) { 605 } 606 /** Discards the specified byte array. */ 607 @Override public void write(byte[] b) { 608 checkNotNull(b); 609 } 610 /** Discards the specified byte array. */ 611 @Override public void write(byte[] b, int off, int len) { 612 checkNotNull(b); 613 } 614 615 @Override 616 public String toString() { 617 return "ByteStreams.nullOutputStream()"; 618 } 619 }; 620 621 /** 622 * Returns an {@link OutputStream} that simply discards written bytes. 623 * 624 * @since 14.0 (since 1.0 as com.google.common.io.NullOutputStream) 625 */ 626 public static OutputStream nullOutputStream() { 627 return NULL_OUTPUT_STREAM; 628 } 629 630 /** 631 * Wraps a {@link InputStream}, limiting the number of bytes which can be 632 * read. 633 * 634 * @param in the input stream to be wrapped 635 * @param limit the maximum number of bytes to be read 636 * @return a length-limited {@link InputStream} 637 * @since 14.0 (since 1.0 as com.google.common.io.LimitInputStream) 638 */ 639 public static InputStream limit(InputStream in, long limit) { 640 return new LimitedInputStream(in, limit); 641 } 642 643 private static final class LimitedInputStream extends FilterInputStream { 644 645 private long left; 646 private long mark = -1; 647 648 LimitedInputStream(InputStream in, long limit) { 649 super(in); 650 checkNotNull(in); 651 checkArgument(limit >= 0, "limit must be non-negative"); 652 left = limit; 653 } 654 655 @Override public int available() throws IOException { 656 return (int) Math.min(in.available(), left); 657 } 658 659 // it's okay to mark even if mark isn't supported, as reset won't work 660 @Override public synchronized void mark(int readLimit) { 661 in.mark(readLimit); 662 mark = left; 663 } 664 665 @Override public int read() throws IOException { 666 if (left == 0) { 667 return -1; 668 } 669 670 int result = in.read(); 671 if (result != -1) { 672 --left; 673 } 674 return result; 675 } 676 677 @Override public int read(byte[] b, int off, int len) throws IOException { 678 if (left == 0) { 679 return -1; 680 } 681 682 len = (int) Math.min(len, left); 683 int result = in.read(b, off, len); 684 if (result != -1) { 685 left -= result; 686 } 687 return result; 688 } 689 690 @Override public synchronized void reset() throws IOException { 691 if (!in.markSupported()) { 692 throw new IOException("Mark not supported"); 693 } 694 if (mark == -1) { 695 throw new IOException("Mark not set"); 696 } 697 698 in.reset(); 699 left = mark; 700 } 701 702 @Override public long skip(long n) throws IOException { 703 n = Math.min(n, left); 704 long skipped = in.skip(n); 705 left -= skipped; 706 return skipped; 707 } 708 } 709 710 /** 711 * Returns the length of a supplied input stream, in bytes. 712 * 713 * @deprecated Use {@link ByteSource#size()} instead. This method is 714 * scheduled for removal in Guava 18.0. 715 */ 716 @Deprecated 717 public static long length( 718 InputSupplier<? extends InputStream> supplier) throws IOException { 719 return asByteSource(supplier).size(); 720 } 721 722 /** 723 * Returns true if the supplied input streams contain the same bytes. 724 * 725 * @throws IOException if an I/O error occurs 726 * @deprecated Use {@link ByteSource#contentEquals(ByteSource)} instead. This 727 * method is scheduled for removal in Guava 18.0. 728 */ 729 @Deprecated 730 public static boolean equal(InputSupplier<? extends InputStream> supplier1, 731 InputSupplier<? extends InputStream> supplier2) throws IOException { 732 return asByteSource(supplier1).contentEquals(asByteSource(supplier2)); 733 } 734 735 /** 736 * Attempts to read enough bytes from the stream to fill the given byte array, 737 * with the same behavior as {@link DataInput#readFully(byte[])}. 738 * Does not close the stream. 739 * 740 * @param in the input stream to read from. 741 * @param b the buffer into which the data is read. 742 * @throws EOFException if this stream reaches the end before reading all 743 * the bytes. 744 * @throws IOException if an I/O error occurs. 745 */ 746 public static void readFully(InputStream in, byte[] b) throws IOException { 747 readFully(in, b, 0, b.length); 748 } 749 750 /** 751 * Attempts to read {@code len} bytes from the stream into the given array 752 * starting at {@code off}, with the same behavior as 753 * {@link DataInput#readFully(byte[], int, int)}. Does not close the 754 * stream. 755 * 756 * @param in the input stream to read from. 757 * @param b the buffer into which the data is read. 758 * @param off an int specifying the offset into the data. 759 * @param len an int specifying the number of bytes to read. 760 * @throws EOFException if this stream reaches the end before reading all 761 * the bytes. 762 * @throws IOException if an I/O error occurs. 763 */ 764 public static void readFully( 765 InputStream in, byte[] b, int off, int len) throws IOException { 766 int read = read(in, b, off, len); 767 if (read != len) { 768 throw new EOFException("reached end of stream after reading " 769 + read + " bytes; " + len + " bytes expected"); 770 } 771 } 772 773 /** 774 * Discards {@code n} bytes of data from the input stream. This method 775 * will block until the full amount has been skipped. Does not close the 776 * stream. 777 * 778 * @param in the input stream to read from 779 * @param n the number of bytes to skip 780 * @throws EOFException if this stream reaches the end before skipping all 781 * the bytes 782 * @throws IOException if an I/O error occurs, or the stream does not 783 * support skipping 784 */ 785 public static void skipFully(InputStream in, long n) throws IOException { 786 long toSkip = n; 787 while (n > 0) { 788 long amt = in.skip(n); 789 if (amt == 0) { 790 // Force a blocking read to avoid infinite loop 791 if (in.read() == -1) { 792 long skipped = toSkip - n; 793 throw new EOFException("reached end of stream after skipping " 794 + skipped + " bytes; " + toSkip + " bytes expected"); 795 } 796 n--; 797 } else { 798 n -= amt; 799 } 800 } 801 } 802 803 /** 804 * Process the bytes of a supplied stream 805 * 806 * @param supplier the input stream factory 807 * @param processor the object to which to pass the bytes of the stream 808 * @return the result of the byte processor 809 * @throws IOException if an I/O error occurs 810 * @deprecated Use {@link ByteSource#read(ByteProcessor)} instead. This 811 * method is scheduled for removal in Guava 18.0. 812 */ 813 @Deprecated 814 public static <T> T readBytes( 815 InputSupplier<? extends InputStream> supplier, 816 ByteProcessor<T> processor) throws IOException { 817 checkNotNull(supplier); 818 checkNotNull(processor); 819 820 Closer closer = Closer.create(); 821 try { 822 InputStream in = closer.register(supplier.getInput()); 823 return readBytes(in, processor); 824 } catch (Throwable e) { 825 throw closer.rethrow(e); 826 } finally { 827 closer.close(); 828 } 829 } 830 831 /** 832 * Process the bytes of the given input stream using the given processor. 833 * 834 * @param input the input stream to process 835 * @param processor the object to which to pass the bytes of the stream 836 * @return the result of the byte processor 837 * @throws IOException if an I/O error occurs 838 * @since 14.0 839 */ 840 public static <T> T readBytes( 841 InputStream input, ByteProcessor<T> processor) throws IOException { 842 checkNotNull(input); 843 checkNotNull(processor); 844 845 byte[] buf = new byte[BUF_SIZE]; 846 int read; 847 do { 848 read = input.read(buf); 849 } while (read != -1 && processor.processBytes(buf, 0, read)); 850 return processor.getResult(); 851 } 852 853 /** 854 * Computes the hash code of the data supplied by {@code supplier} using {@code 855 * hashFunction}. 856 * 857 * @param supplier the input stream factory 858 * @param hashFunction the hash function to use to hash the data 859 * @return the {@link HashCode} of all of the bytes in the input stream 860 * @throws IOException if an I/O error occurs 861 * @since 12.0 862 * @deprecated Use {@link ByteSource#hash(HashFunction)} instead. This method 863 * is scheduled for removal in Guava 18.0. 864 */ 865 @Deprecated 866 public static HashCode hash( 867 InputSupplier<? extends InputStream> supplier, HashFunction hashFunction) 868 throws IOException { 869 return asByteSource(supplier).hash(hashFunction); 870 } 871 872 /** 873 * Reads some bytes from an input stream and stores them into the buffer array 874 * {@code b}. This method blocks until {@code len} bytes of input data have 875 * been read into the array, or end of file is detected. The number of bytes 876 * read is returned, possibly zero. Does not close the stream. 877 * 878 * <p>A caller can detect EOF if the number of bytes read is less than 879 * {@code len}. All subsequent calls on the same stream will return zero. 880 * 881 * <p>If {@code b} is null, a {@code NullPointerException} is thrown. If 882 * {@code off} is negative, or {@code len} is negative, or {@code off+len} is 883 * greater than the length of the array {@code b}, then an 884 * {@code IndexOutOfBoundsException} is thrown. If {@code len} is zero, then 885 * no bytes are read. Otherwise, the first byte read is stored into element 886 * {@code b[off]}, the next one into {@code b[off+1]}, and so on. The number 887 * of bytes read is, at most, equal to {@code len}. 888 * 889 * @param in the input stream to read from 890 * @param b the buffer into which the data is read 891 * @param off an int specifying the offset into the data 892 * @param len an int specifying the number of bytes to read 893 * @return the number of bytes read 894 * @throws IOException if an I/O error occurs 895 */ 896 public static int read(InputStream in, byte[] b, int off, int len) 897 throws IOException { 898 checkNotNull(in); 899 checkNotNull(b); 900 if (len < 0) { 901 throw new IndexOutOfBoundsException("len is negative"); 902 } 903 int total = 0; 904 while (total < len) { 905 int result = in.read(b, off + total, len - total); 906 if (result == -1) { 907 break; 908 } 909 total += result; 910 } 911 return total; 912 } 913 914 /** 915 * Returns an {@link InputSupplier} that returns input streams from the 916 * an underlying supplier, where each stream starts at the given 917 * offset and is limited to the specified number of bytes. 918 * 919 * @param supplier the supplier from which to get the raw streams 920 * @param offset the offset in bytes into the underlying stream where 921 * the returned streams will start 922 * @param length the maximum length of the returned streams 923 * @throws IllegalArgumentException if offset or length are negative 924 * @deprecated Use {@link ByteSource#slice(int, int)} instead. This method is 925 * scheduled for removal in Guava 18.0. 926 */ 927 @Deprecated 928 public static InputSupplier<InputStream> slice( 929 final InputSupplier<? extends InputStream> supplier, 930 final long offset, 931 final long length) { 932 return asInputSupplier(asByteSource(supplier).slice(offset, length)); 933 } 934 935 /** 936 * Joins multiple {@link InputStream} suppliers into a single supplier. 937 * Streams returned from the supplier will contain the concatenated data from 938 * the streams of the underlying suppliers. 939 * 940 * <p>Only one underlying input stream will be open at a time. Closing the 941 * joined stream will close the open underlying stream. 942 * 943 * <p>Reading from the joined stream will throw a {@link NullPointerException} 944 * if any of the suppliers are null or return null. 945 * 946 * @param suppliers the suppliers to concatenate 947 * @return a supplier that will return a stream containing the concatenated 948 * stream data 949 * @deprecated Use {@link ByteSource#concat(Iterable)} instead. This method 950 * is scheduled for removal in Guava 18.0. 951 */ 952 @Deprecated 953 public static InputSupplier<InputStream> join( 954 final Iterable<? extends InputSupplier<? extends InputStream>> suppliers) { 955 checkNotNull(suppliers); 956 Iterable<ByteSource> sources = Iterables.transform(suppliers, 957 new Function<InputSupplier<? extends InputStream>, ByteSource>() { 958 @Override 959 public ByteSource apply(InputSupplier<? extends InputStream> input) { 960 return asByteSource(input); 961 } 962 }); 963 return asInputSupplier(ByteSource.concat(sources)); 964 } 965 966 /** 967 * Varargs form of {@link #join(Iterable)}. 968 * 969 * @deprecated Use {@link ByteSource#concat(ByteSource[])} instead. This 970 * method is scheduled for removal in Guava 18.0. 971 */ 972 @Deprecated 973 @SuppressWarnings("unchecked") // suppress "possible heap pollution" warning in JDK7 974 public static InputSupplier<InputStream> join( 975 InputSupplier<? extends InputStream>... suppliers) { 976 return join(Arrays.asList(suppliers)); 977 } 978 979 // TODO(user): Remove these once Input/OutputSupplier methods are removed 980 981 /** 982 * Returns a view of the given {@code InputStream} supplier as a 983 * {@code ByteSource}. 984 * 985 * <p>This method is a temporary method provided for easing migration from 986 * suppliers to sources and sinks. 987 * 988 * @since 15.0 989 * @deprecated Convert all {@code InputSupplier<? extends InputStream>} 990 * implementations to extend {@link ByteSource} or provide a method for 991 * viewing the object as a {@code ByteSource}. This method is scheduled 992 * for removal in Guava 18.0. 993 */ 994 @Deprecated 995 public static ByteSource asByteSource( 996 final InputSupplier<? extends InputStream> supplier) { 997 checkNotNull(supplier); 998 return new ByteSource() { 999 @Override 1000 public InputStream openStream() throws IOException { 1001 return supplier.getInput(); 1002 } 1003 1004 @Override 1005 public String toString() { 1006 return "ByteStreams.asByteSource(" + supplier + ")"; 1007 } 1008 }; 1009 } 1010 1011 /** 1012 * Returns a view of the given {@code OutputStream} supplier as a 1013 * {@code ByteSink}. 1014 * 1015 * <p>This method is a temporary method provided for easing migration from 1016 * suppliers to sources and sinks. 1017 * 1018 * @since 15.0 1019 * @deprecated Convert all {@code OutputSupplier<? extends OutputStream>} 1020 * implementations to extend {@link ByteSink} or provide a method for 1021 * viewing the object as a {@code ByteSink}. This method is scheduled 1022 * for removal in Guava 18.0. 1023 */ 1024 @Deprecated 1025 public static ByteSink asByteSink( 1026 final OutputSupplier<? extends OutputStream> supplier) { 1027 checkNotNull(supplier); 1028 return new ByteSink() { 1029 @Override 1030 public OutputStream openStream() throws IOException { 1031 return supplier.getOutput(); 1032 } 1033 1034 @Override 1035 public String toString() { 1036 return "ByteStreams.asByteSink(" + supplier + ")"; 1037 } 1038 }; 1039 } 1040 1041 @SuppressWarnings("unchecked") // used internally where known to be safe 1042 static <S extends InputStream> InputSupplier<S> asInputSupplier( 1043 final ByteSource source) { 1044 return (InputSupplier) checkNotNull(source); 1045 } 1046 1047 @SuppressWarnings("unchecked") // used internally where known to be safe 1048 static <S extends OutputStream> OutputSupplier<S> asOutputSupplier( 1049 final ByteSink sink) { 1050 return (OutputSupplier) checkNotNull(sink); 1051 } 1052}