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