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