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