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