ByteStreams.java revision 5cab40b862c21656c2ace19596874eb3ffe1b649
1/* 2 * Copyright (C) 2007 The Guava Authors 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.google.common.io; 18 19import static com.google.common.base.Preconditions.checkArgument; 20import static com.google.common.base.Preconditions.checkNotNull; 21import static com.google.common.base.Preconditions.checkPositionIndex; 22 23import com.google.common.annotations.Beta; 24import com.google.common.base.Function; 25import com.google.common.collect.Iterables; 26import com.google.common.hash.HashCode; 27import com.google.common.hash.HashFunction; 28 29import java.io.ByteArrayInputStream; 30import java.io.ByteArrayOutputStream; 31import java.io.DataInput; 32import java.io.DataInputStream; 33import java.io.DataOutput; 34import java.io.DataOutputStream; 35import java.io.EOFException; 36import java.io.FilterInputStream; 37import java.io.IOException; 38import java.io.InputStream; 39import java.io.OutputStream; 40import java.nio.ByteBuffer; 41import java.nio.channels.ReadableByteChannel; 42import java.nio.channels.WritableByteChannel; 43import java.util.Arrays; 44 45/** 46 * Provides utility methods for working with byte arrays and I/O streams. 47 * 48 * @author Chris Nokleberg 49 * @author Colin Decker 50 * @since 1.0 51 */ 52@Beta 53public final class ByteStreams { 54 private static final int BUF_SIZE = 0x1000; // 4K 55 56 private ByteStreams() {} 57 58 /** 59 * Returns a factory that will supply instances of 60 * {@link ByteArrayInputStream} that read from the given byte array. 61 * 62 * @param b the input buffer 63 * @return the factory 64 * @deprecated Use {@link ByteSource#wrap(byte[])} instead. This method is 65 * scheduled for removal in Guava 18.0. 66 */ 67 @Deprecated 68 public static InputSupplier<ByteArrayInputStream> newInputStreamSupplier( 69 byte[] b) { 70 return asInputSupplier(ByteSource.wrap(b)); 71 } 72 73 /** 74 * Returns a factory that will supply instances of 75 * {@link ByteArrayInputStream} that read from the given byte array. 76 * 77 * @param b the input buffer 78 * @param off the offset in the buffer of the first byte to read 79 * @param len the maximum number of bytes to read from the buffer 80 * @return the factory 81 * @deprecated Use {@code ByteSource.wrap(b).slice(off, len)} instead. This 82 * method is scheduled for removal in Guava 18.0. 83 */ 84 @Deprecated 85 public static InputSupplier<ByteArrayInputStream> newInputStreamSupplier( 86 final byte[] b, final int off, final int len) { 87 return asInputSupplier(ByteSource.wrap(b).slice(off, len)); 88 } 89 90 /** 91 * Writes a byte array to an output stream from the given supplier. 92 * 93 * @param from the bytes to write 94 * @param to the output supplier 95 * @throws IOException if an I/O error occurs 96 * @deprecated Use {@link ByteSink#write(byte[])} instead. This method is 97 * scheduled for removal in Guava 18.0. 98 */ 99 @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 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 private static byte[] copyOf(byte[] array, int length) { 264 byte[] newArray = new byte[length]; 265 System.arraycopy(array, 0, newArray, 0, length); 266 return newArray; 267 } 268 269 /** 270 * BAOS that provides limited access to its internal byte array. 271 */ 272 private static final class FastByteArrayOutputStream 273 extends ByteArrayOutputStream { 274 /** 275 * Writes the contents of the internal buffer to the given array starting 276 * at the given offset. Assumes the array has space to hold count bytes. 277 */ 278 void writeTo(byte[] b, int off) { 279 System.arraycopy(buf, 0, b, off, count); 280 } 281 } 282 283 /** 284 * Returns the data from a {@link InputStream} factory as a byte array. 285 * 286 * @param supplier the factory 287 * @throws IOException if an I/O error occurs 288 * @deprecated Use {@link ByteSource#read()} instead. This method is 289 * scheduled for removal in Guava 18.0. 290 */ 291 @Deprecated 292 public static byte[] toByteArray( 293 InputSupplier<? extends InputStream> supplier) throws IOException { 294 return asByteSource(supplier).read(); 295 } 296 297 /** 298 * Returns a new {@link ByteArrayDataInput} instance to read from the {@code 299 * bytes} array from the beginning. 300 */ 301 public static ByteArrayDataInput newDataInput(byte[] bytes) { 302 return newDataInput(new ByteArrayInputStream(bytes)); 303 } 304 305 /** 306 * Returns a new {@link ByteArrayDataInput} instance to read from the {@code 307 * bytes} array, starting at the given position. 308 * 309 * @throws IndexOutOfBoundsException if {@code start} is negative or greater 310 * than the length of the array 311 */ 312 public static ByteArrayDataInput newDataInput(byte[] bytes, int start) { 313 checkPositionIndex(start, bytes.length); 314 return newDataInput( 315 new ByteArrayInputStream(bytes, start, bytes.length - start)); 316 } 317 318 /** 319 * Returns a new {@link ByteArrayDataInput} instance to read from the given 320 * {@code ByteArrayInputStream}. The given input stream is not reset before 321 * being read from by the returned {@code ByteArrayDataInput}. 322 * 323 * @since 17.0 324 */ 325 public static ByteArrayDataInput newDataInput( 326 ByteArrayInputStream byteArrayInputStream) { 327 return new ByteArrayDataInputStream(checkNotNull(byteArrayInputStream)); 328 } 329 330 private static class ByteArrayDataInputStream implements ByteArrayDataInput { 331 final DataInput input; 332 333 ByteArrayDataInputStream(ByteArrayInputStream byteArrayInputStream) { 334 this.input = new DataInputStream(byteArrayInputStream); 335 } 336 337 @Override public void readFully(byte b[]) { 338 try { 339 input.readFully(b); 340 } catch (IOException e) { 341 throw new IllegalStateException(e); 342 } 343 } 344 345 @Override public void readFully(byte b[], int off, int len) { 346 try { 347 input.readFully(b, off, len); 348 } catch (IOException e) { 349 throw new IllegalStateException(e); 350 } 351 } 352 353 @Override public int skipBytes(int n) { 354 try { 355 return input.skipBytes(n); 356 } catch (IOException e) { 357 throw new IllegalStateException(e); 358 } 359 } 360 361 @Override public boolean readBoolean() { 362 try { 363 return input.readBoolean(); 364 } catch (IOException e) { 365 throw new IllegalStateException(e); 366 } 367 } 368 369 @Override public byte readByte() { 370 try { 371 return input.readByte(); 372 } catch (EOFException e) { 373 throw new IllegalStateException(e); 374 } catch (IOException impossible) { 375 throw new AssertionError(impossible); 376 } 377 } 378 379 @Override public int readUnsignedByte() { 380 try { 381 return input.readUnsignedByte(); 382 } catch (IOException e) { 383 throw new IllegalStateException(e); 384 } 385 } 386 387 @Override public short readShort() { 388 try { 389 return input.readShort(); 390 } catch (IOException e) { 391 throw new IllegalStateException(e); 392 } 393 } 394 395 @Override public int readUnsignedShort() { 396 try { 397 return input.readUnsignedShort(); 398 } catch (IOException e) { 399 throw new IllegalStateException(e); 400 } 401 } 402 403 @Override public char readChar() { 404 try { 405 return input.readChar(); 406 } catch (IOException e) { 407 throw new IllegalStateException(e); 408 } 409 } 410 411 @Override public int readInt() { 412 try { 413 return input.readInt(); 414 } catch (IOException e) { 415 throw new IllegalStateException(e); 416 } 417 } 418 419 @Override public long readLong() { 420 try { 421 return input.readLong(); 422 } catch (IOException e) { 423 throw new IllegalStateException(e); 424 } 425 } 426 427 @Override public float readFloat() { 428 try { 429 return input.readFloat(); 430 } catch (IOException e) { 431 throw new IllegalStateException(e); 432 } 433 } 434 435 @Override public double readDouble() { 436 try { 437 return input.readDouble(); 438 } catch (IOException e) { 439 throw new IllegalStateException(e); 440 } 441 } 442 443 @Override public String readLine() { 444 try { 445 return input.readLine(); 446 } catch (IOException e) { 447 throw new IllegalStateException(e); 448 } 449 } 450 451 @Override public String readUTF() { 452 try { 453 return input.readUTF(); 454 } catch (IOException e) { 455 throw new IllegalStateException(e); 456 } 457 } 458 } 459 460 /** 461 * Returns a new {@link ByteArrayDataOutput} instance with a default size. 462 */ 463 public static ByteArrayDataOutput newDataOutput() { 464 return newDataOutput(new ByteArrayOutputStream()); 465 } 466 467 /** 468 * Returns a new {@link ByteArrayDataOutput} instance sized to hold 469 * {@code size} bytes before resizing. 470 * 471 * @throws IllegalArgumentException if {@code size} is negative 472 */ 473 public static ByteArrayDataOutput newDataOutput(int size) { 474 checkArgument(size >= 0, "Invalid size: %s", size); 475 return newDataOutput(new ByteArrayOutputStream(size)); 476 } 477 478 /** 479 * Returns a new {@link ByteArrayDataOutput} instance which writes to the 480 * given {@code ByteArrayOutputStream}. The given output stream is not reset 481 * before being written to by the returned {@code ByteArrayDataOutput} and 482 * new data will be appended to any existing content. 483 * 484 * <p>Note that if the given output stream was not empty or is modified after 485 * the {@code ByteArrayDataOutput} is created, the contract for 486 * {@link ByteArrayDataOutput#toByteArray} will not be honored (the bytes 487 * returned in the byte array may not be exactly what was written via calls to 488 * {@code ByteArrayDataOutput}). 489 * 490 * @since 17.0 491 */ 492 public static ByteArrayDataOutput newDataOutput( 493 ByteArrayOutputStream byteArrayOutputSteam) { 494 return new ByteArrayDataOutputStream(checkNotNull(byteArrayOutputSteam)); 495 } 496 497 @SuppressWarnings("deprecation") // for writeBytes 498 private static class ByteArrayDataOutputStream 499 implements ByteArrayDataOutput { 500 501 final DataOutput output; 502 final ByteArrayOutputStream byteArrayOutputSteam; 503 504 ByteArrayDataOutputStream(ByteArrayOutputStream byteArrayOutputSteam) { 505 this.byteArrayOutputSteam = byteArrayOutputSteam; 506 output = new DataOutputStream(byteArrayOutputSteam); 507 } 508 509 @Override public void write(int b) { 510 try { 511 output.write(b); 512 } catch (IOException impossible) { 513 throw new AssertionError(impossible); 514 } 515 } 516 517 @Override public void write(byte[] b) { 518 try { 519 output.write(b); 520 } catch (IOException impossible) { 521 throw new AssertionError(impossible); 522 } 523 } 524 525 @Override public void write(byte[] b, int off, int len) { 526 try { 527 output.write(b, off, len); 528 } catch (IOException impossible) { 529 throw new AssertionError(impossible); 530 } 531 } 532 533 @Override public void writeBoolean(boolean v) { 534 try { 535 output.writeBoolean(v); 536 } catch (IOException impossible) { 537 throw new AssertionError(impossible); 538 } 539 } 540 541 @Override public void writeByte(int v) { 542 try { 543 output.writeByte(v); 544 } catch (IOException impossible) { 545 throw new AssertionError(impossible); 546 } 547 } 548 549 @Override public void writeBytes(String s) { 550 try { 551 output.writeBytes(s); 552 } catch (IOException impossible) { 553 throw new AssertionError(impossible); 554 } 555 } 556 557 @Override public void writeChar(int v) { 558 try { 559 output.writeChar(v); 560 } catch (IOException impossible) { 561 throw new AssertionError(impossible); 562 } 563 } 564 565 @Override public void writeChars(String s) { 566 try { 567 output.writeChars(s); 568 } catch (IOException impossible) { 569 throw new AssertionError(impossible); 570 } 571 } 572 573 @Override public void writeDouble(double v) { 574 try { 575 output.writeDouble(v); 576 } catch (IOException impossible) { 577 throw new AssertionError(impossible); 578 } 579 } 580 581 @Override public void writeFloat(float v) { 582 try { 583 output.writeFloat(v); 584 } catch (IOException impossible) { 585 throw new AssertionError(impossible); 586 } 587 } 588 589 @Override public void writeInt(int v) { 590 try { 591 output.writeInt(v); 592 } catch (IOException impossible) { 593 throw new AssertionError(impossible); 594 } 595 } 596 597 @Override public void writeLong(long v) { 598 try { 599 output.writeLong(v); 600 } catch (IOException impossible) { 601 throw new AssertionError(impossible); 602 } 603 } 604 605 @Override public void writeShort(int v) { 606 try { 607 output.writeShort(v); 608 } catch (IOException impossible) { 609 throw new AssertionError(impossible); 610 } 611 } 612 613 @Override public void writeUTF(String s) { 614 try { 615 output.writeUTF(s); 616 } catch (IOException impossible) { 617 throw new AssertionError(impossible); 618 } 619 } 620 621 @Override public byte[] toByteArray() { 622 return byteArrayOutputSteam.toByteArray(); 623 } 624 } 625 626 private static final OutputStream NULL_OUTPUT_STREAM = 627 new OutputStream() { 628 /** Discards the specified byte. */ 629 @Override public void write(int b) { 630 } 631 /** Discards the specified byte array. */ 632 @Override public void write(byte[] b) { 633 checkNotNull(b); 634 } 635 /** Discards the specified byte array. */ 636 @Override public void write(byte[] b, int off, int len) { 637 checkNotNull(b); 638 } 639 640 @Override 641 public String toString() { 642 return "ByteStreams.nullOutputStream()"; 643 } 644 }; 645 646 /** 647 * Returns an {@link OutputStream} that simply discards written bytes. 648 * 649 * @since 14.0 (since 1.0 as com.google.common.io.NullOutputStream) 650 */ 651 public static OutputStream nullOutputStream() { 652 return NULL_OUTPUT_STREAM; 653 } 654 655 /** 656 * Wraps a {@link InputStream}, limiting the number of bytes which can be 657 * read. 658 * 659 * @param in the input stream to be wrapped 660 * @param limit the maximum number of bytes to be read 661 * @return a length-limited {@link InputStream} 662 * @since 14.0 (since 1.0 as com.google.common.io.LimitInputStream) 663 */ 664 public static InputStream limit(InputStream in, long limit) { 665 return new LimitedInputStream(in, limit); 666 } 667 668 private static final class LimitedInputStream extends FilterInputStream { 669 670 private long left; 671 private long mark = -1; 672 673 LimitedInputStream(InputStream in, long limit) { 674 super(in); 675 checkNotNull(in); 676 checkArgument(limit >= 0, "limit must be non-negative"); 677 left = limit; 678 } 679 680 @Override public int available() throws IOException { 681 return (int) Math.min(in.available(), left); 682 } 683 684 // it's okay to mark even if mark isn't supported, as reset won't work 685 @Override public synchronized void mark(int readLimit) { 686 in.mark(readLimit); 687 mark = left; 688 } 689 690 @Override public int read() throws IOException { 691 if (left == 0) { 692 return -1; 693 } 694 695 int result = in.read(); 696 if (result != -1) { 697 --left; 698 } 699 return result; 700 } 701 702 @Override public int read(byte[] b, int off, int len) throws IOException { 703 if (left == 0) { 704 return -1; 705 } 706 707 len = (int) Math.min(len, left); 708 int result = in.read(b, off, len); 709 if (result != -1) { 710 left -= result; 711 } 712 return result; 713 } 714 715 @Override public synchronized void reset() throws IOException { 716 if (!in.markSupported()) { 717 throw new IOException("Mark not supported"); 718 } 719 if (mark == -1) { 720 throw new IOException("Mark not set"); 721 } 722 723 in.reset(); 724 left = mark; 725 } 726 727 @Override public long skip(long n) throws IOException { 728 n = Math.min(n, left); 729 long skipped = in.skip(n); 730 left -= skipped; 731 return skipped; 732 } 733 } 734 735 /** 736 * Returns the length of a supplied input stream, in bytes. 737 * 738 * @deprecated Use {@link ByteSource#size()} instead. This method is 739 * scheduled for removal in Guava 18.0. 740 */ 741 @Deprecated 742 public static long length( 743 InputSupplier<? extends InputStream> supplier) throws IOException { 744 return asByteSource(supplier).size(); 745 } 746 747 /** 748 * Returns true if the supplied input streams contain the same bytes. 749 * 750 * @throws IOException if an I/O error occurs 751 * @deprecated Use {@link ByteSource#contentEquals(ByteSource)} instead. This 752 * method is scheduled for removal in Guava 18.0. 753 */ 754 @Deprecated 755 public static boolean equal(InputSupplier<? extends InputStream> supplier1, 756 InputSupplier<? extends InputStream> supplier2) throws IOException { 757 return asByteSource(supplier1).contentEquals(asByteSource(supplier2)); 758 } 759 760 /** 761 * Attempts to read enough bytes from the stream to fill the given byte array, 762 * with the same behavior as {@link DataInput#readFully(byte[])}. 763 * Does not close the stream. 764 * 765 * @param in the input stream to read from. 766 * @param b the buffer into which the data is read. 767 * @throws EOFException if this stream reaches the end before reading all 768 * the bytes. 769 * @throws IOException if an I/O error occurs. 770 */ 771 public static void readFully(InputStream in, byte[] b) throws IOException { 772 readFully(in, b, 0, b.length); 773 } 774 775 /** 776 * Attempts to read {@code len} bytes from the stream into the given array 777 * starting at {@code off}, with the same behavior as 778 * {@link DataInput#readFully(byte[], int, int)}. Does not close the 779 * stream. 780 * 781 * @param in the input stream to read from. 782 * @param b the buffer into which the data is read. 783 * @param off an int specifying the offset into the data. 784 * @param len an int specifying the number of bytes to read. 785 * @throws EOFException if this stream reaches the end before reading all 786 * the bytes. 787 * @throws IOException if an I/O error occurs. 788 */ 789 public static void readFully( 790 InputStream in, byte[] b, int off, int len) throws IOException { 791 int read = read(in, b, off, len); 792 if (read != len) { 793 throw new EOFException("reached end of stream after reading " 794 + read + " bytes; " + len + " bytes expected"); 795 } 796 } 797 798 /** 799 * Discards {@code n} bytes of data from the input stream. This method 800 * will block until the full amount has been skipped. Does not close the 801 * stream. 802 * 803 * @param in the input stream to read from 804 * @param n the number of bytes to skip 805 * @throws EOFException if this stream reaches the end before skipping all 806 * the bytes 807 * @throws IOException if an I/O error occurs, or the stream does not 808 * support skipping 809 */ 810 public static void skipFully(InputStream in, long n) throws IOException { 811 long toSkip = n; 812 while (n > 0) { 813 long amt = in.skip(n); 814 if (amt == 0) { 815 // Force a blocking read to avoid infinite loop 816 if (in.read() == -1) { 817 long skipped = toSkip - n; 818 throw new EOFException("reached end of stream after skipping " 819 + skipped + " bytes; " + toSkip + " bytes expected"); 820 } 821 n--; 822 } else { 823 n -= amt; 824 } 825 } 826 } 827 828 /** 829 * Process the bytes of a supplied stream 830 * 831 * @param supplier the input stream factory 832 * @param processor the object to which to pass the bytes of the stream 833 * @return the result of the byte processor 834 * @throws IOException if an I/O error occurs 835 * @deprecated Use {@link ByteSource#read(ByteProcessor)} instead. This 836 * method is scheduled for removal in Guava 18.0. 837 */ 838 @Deprecated 839 public static <T> T readBytes( 840 InputSupplier<? extends InputStream> supplier, 841 ByteProcessor<T> processor) throws IOException { 842 checkNotNull(supplier); 843 checkNotNull(processor); 844 845 Closer closer = Closer.create(); 846 try { 847 InputStream in = closer.register(supplier.getInput()); 848 return readBytes(in, processor); 849 } catch (Throwable e) { 850 throw closer.rethrow(e); 851 } finally { 852 closer.close(); 853 } 854 } 855 856 /** 857 * Process the bytes of the given input stream using the given processor. 858 * 859 * @param input the input stream to process 860 * @param processor the object to which to pass the bytes of the stream 861 * @return the result of the byte processor 862 * @throws IOException if an I/O error occurs 863 * @since 14.0 864 */ 865 public static <T> T readBytes( 866 InputStream input, ByteProcessor<T> processor) throws IOException { 867 checkNotNull(input); 868 checkNotNull(processor); 869 870 byte[] buf = new byte[BUF_SIZE]; 871 int read; 872 do { 873 read = input.read(buf); 874 } while (read != -1 && processor.processBytes(buf, 0, read)); 875 return processor.getResult(); 876 } 877 878 /** 879 * Computes the hash code of the data supplied by {@code supplier} using {@code 880 * hashFunction}. 881 * 882 * @param supplier the input stream factory 883 * @param hashFunction the hash function to use to hash the data 884 * @return the {@link HashCode} of all of the bytes in the input stream 885 * @throws IOException if an I/O error occurs 886 * @since 12.0 887 * @deprecated Use {@link ByteSource#hash(HashFunction)} instead. This method 888 * is scheduled for removal in Guava 18.0. 889 */ 890 @Deprecated 891 public static HashCode hash( 892 InputSupplier<? extends InputStream> supplier, HashFunction hashFunction) 893 throws IOException { 894 return asByteSource(supplier).hash(hashFunction); 895 } 896 897 /** 898 * Reads some bytes from an input stream and stores them into the buffer array 899 * {@code b}. This method blocks until {@code len} bytes of input data have 900 * been read into the array, or end of file is detected. The number of bytes 901 * read is returned, possibly zero. Does not close the stream. 902 * 903 * <p>A caller can detect EOF if the number of bytes read is less than 904 * {@code len}. All subsequent calls on the same stream will return zero. 905 * 906 * <p>If {@code b} is null, a {@code NullPointerException} is thrown. If 907 * {@code off} is negative, or {@code len} is negative, or {@code off+len} is 908 * greater than the length of the array {@code b}, then an 909 * {@code IndexOutOfBoundsException} is thrown. If {@code len} is zero, then 910 * no bytes are read. Otherwise, the first byte read is stored into element 911 * {@code b[off]}, the next one into {@code b[off+1]}, and so on. The number 912 * of bytes read is, at most, equal to {@code len}. 913 * 914 * @param in the input stream to read from 915 * @param b the buffer into which the data is read 916 * @param off an int specifying the offset into the data 917 * @param len an int specifying the number of bytes to read 918 * @return the number of bytes read 919 * @throws IOException if an I/O error occurs 920 */ 921 public static int read(InputStream in, byte[] b, int off, int len) 922 throws IOException { 923 checkNotNull(in); 924 checkNotNull(b); 925 if (len < 0) { 926 throw new IndexOutOfBoundsException("len is negative"); 927 } 928 int total = 0; 929 while (total < len) { 930 int result = in.read(b, off + total, len - total); 931 if (result == -1) { 932 break; 933 } 934 total += result; 935 } 936 return total; 937 } 938 939 /** 940 * Returns an {@link InputSupplier} that returns input streams from the 941 * an underlying supplier, where each stream starts at the given 942 * offset and is limited to the specified number of bytes. 943 * 944 * @param supplier the supplier from which to get the raw streams 945 * @param offset the offset in bytes into the underlying stream where 946 * the returned streams will start 947 * @param length the maximum length of the returned streams 948 * @throws IllegalArgumentException if offset or length are negative 949 * @deprecated Use {@link ByteSource#slice(int, int)} instead. This method is 950 * scheduled for removal in Guava 18.0. 951 */ 952 @Deprecated 953 public static InputSupplier<InputStream> slice( 954 final InputSupplier<? extends InputStream> supplier, 955 final long offset, 956 final long length) { 957 return asInputSupplier(asByteSource(supplier).slice(offset, length)); 958 } 959 960 /** 961 * Joins multiple {@link InputStream} suppliers into a single supplier. 962 * Streams returned from the supplier will contain the concatenated data from 963 * the streams of the underlying suppliers. 964 * 965 * <p>Only one underlying input stream will be open at a time. Closing the 966 * joined stream will close the open underlying stream. 967 * 968 * <p>Reading from the joined stream will throw a {@link NullPointerException} 969 * if any of the suppliers are null or return null. 970 * 971 * @param suppliers the suppliers to concatenate 972 * @return a supplier that will return a stream containing the concatenated 973 * stream data 974 * @deprecated Use {@link ByteSource#concat(Iterable)} instead. This method 975 * is scheduled for removal in Guava 18.0. 976 */ 977 @Deprecated 978 public static InputSupplier<InputStream> join( 979 final Iterable<? extends InputSupplier<? extends InputStream>> suppliers) { 980 checkNotNull(suppliers); 981 Iterable<ByteSource> sources = Iterables.transform(suppliers, 982 new Function<InputSupplier<? extends InputStream>, ByteSource>() { 983 @Override 984 public ByteSource apply(InputSupplier<? extends InputStream> input) { 985 return asByteSource(input); 986 } 987 }); 988 return asInputSupplier(ByteSource.concat(sources)); 989 } 990 991 /** 992 * Varargs form of {@link #join(Iterable)}. 993 * 994 * @deprecated Use {@link ByteSource#concat(ByteSource[])} instead. This 995 * method is scheduled for removal in Guava 18.0. 996 */ 997 @Deprecated 998 @SuppressWarnings("unchecked") // suppress "possible heap pollution" warning in JDK7 999 public static InputSupplier<InputStream> join( 1000 InputSupplier<? extends InputStream>... suppliers) { 1001 return join(Arrays.asList(suppliers)); 1002 } 1003 1004 // TODO(user): Remove these once Input/OutputSupplier methods are removed 1005 1006 /** 1007 * Returns a view of the given {@code InputStream} supplier as a 1008 * {@code ByteSource}. 1009 * 1010 * <p>This method is a temporary method provided for easing migration from 1011 * suppliers to sources and sinks. 1012 * 1013 * @since 15.0 1014 * @deprecated Convert all {@code InputSupplier<? extends InputStream>} 1015 * implementations to extend {@link ByteSource} or provide a method for 1016 * viewing the object as a {@code ByteSource}. This method is scheduled 1017 * for removal in Guava 18.0. 1018 */ 1019 @Deprecated 1020 public static ByteSource asByteSource( 1021 final InputSupplier<? extends InputStream> supplier) { 1022 checkNotNull(supplier); 1023 return new ByteSource() { 1024 @Override 1025 public InputStream openStream() throws IOException { 1026 return supplier.getInput(); 1027 } 1028 1029 @Override 1030 public String toString() { 1031 return "ByteStreams.asByteSource(" + supplier + ")"; 1032 } 1033 }; 1034 } 1035 1036 /** 1037 * Returns a view of the given {@code OutputStream} supplier as a 1038 * {@code ByteSink}. 1039 * 1040 * <p>This method is a temporary method provided for easing migration from 1041 * suppliers to sources and sinks. 1042 * 1043 * @since 15.0 1044 * @deprecated Convert all {@code OutputSupplier<? extends OutputStream>} 1045 * implementations to extend {@link ByteSink} or provide a method for 1046 * viewing the object as a {@code ByteSink}. This method is scheduled 1047 * for removal in Guava 18.0. 1048 */ 1049 @Deprecated 1050 public static ByteSink asByteSink( 1051 final OutputSupplier<? extends OutputStream> supplier) { 1052 checkNotNull(supplier); 1053 return new ByteSink() { 1054 @Override 1055 public OutputStream openStream() throws IOException { 1056 return supplier.getOutput(); 1057 } 1058 1059 @Override 1060 public String toString() { 1061 return "ByteStreams.asByteSink(" + supplier + ")"; 1062 } 1063 }; 1064 } 1065 1066 @SuppressWarnings("unchecked") // used internally where known to be safe 1067 static <S extends InputStream> InputSupplier<S> asInputSupplier( 1068 final ByteSource source) { 1069 return (InputSupplier) checkNotNull(source); 1070 } 1071 1072 @SuppressWarnings("unchecked") // used internally where known to be safe 1073 static <S extends OutputStream> OutputSupplier<S> asOutputSupplier( 1074 final ByteSink sink) { 1075 return (OutputSupplier) checkNotNull(sink); 1076 } 1077} 1078