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