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