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