1bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor/*
21d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Copyright (C) 2007 The Guava Authors
3bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor *
4bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * Licensed under the Apache License, Version 2.0 (the "License");
5bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * you may not use this file except in compliance with the License.
6bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * You may obtain a copy of the License at
7bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor *
8bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * http://www.apache.org/licenses/LICENSE-2.0
9bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor *
10bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * Unless required by applicable law or agreed to in writing, software
11bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * distributed under the License is distributed on an "AS IS" BASIS,
12bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * See the License for the specific language governing permissions and
14bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * limitations under the License.
15bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor */
16bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor
17bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnorpackage com.google.common.io;
18bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor
191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.annotations.Beta;
20bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnorimport com.google.common.base.Preconditions;
21bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor
22bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnorimport java.io.ByteArrayInputStream;
23bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnorimport java.io.ByteArrayOutputStream;
24bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnorimport java.io.DataInput;
25bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnorimport java.io.DataInputStream;
26bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnorimport java.io.DataOutput;
27bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnorimport java.io.DataOutputStream;
28bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnorimport java.io.EOFException;
29bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnorimport java.io.IOException;
30bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnorimport java.io.InputStream;
31bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnorimport java.io.OutputStream;
32bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnorimport java.nio.ByteBuffer;
33bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnorimport java.nio.channels.ReadableByteChannel;
34bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnorimport java.nio.channels.WritableByteChannel;
35bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnorimport java.security.MessageDigest;
36bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnorimport java.util.Arrays;
37bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnorimport java.util.zip.Checksum;
38bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor
39bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor/**
40bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * Provides utility methods for working with byte arrays and I/O streams.
41bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor *
42bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * <p>All method parameters must be non-null unless documented otherwise.
43bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor *
44bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * @author Chris Nokleberg
451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @since 1.0
46bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor */
471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert@Beta
48bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnorpublic final class ByteStreams {
49bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor  private static final int BUF_SIZE = 0x1000; // 4K
50bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor
51bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor  private ByteStreams() {}
52bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor
53bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor  /**
54bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * Returns a factory that will supply instances of
55bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * {@link ByteArrayInputStream} that read from the given byte array.
56bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   *
57bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * @param b the input buffer
58bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * @return the factory
59bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   */
60bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor  public static InputSupplier<ByteArrayInputStream> newInputStreamSupplier(
61bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      byte[] b) {
62bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    return newInputStreamSupplier(b, 0, b.length);
63bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor  }
64bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor
65bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor  /**
66bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * Returns a factory that will supply instances of
67bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * {@link ByteArrayInputStream} that read from the given byte array.
68bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   *
69bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * @param b the input buffer
70bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * @param off the offset in the buffer of the first byte to read
71bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * @param len the maximum number of bytes to read from the buffer
72bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * @return the factory
73bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   */
74bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor  public static InputSupplier<ByteArrayInputStream> newInputStreamSupplier(
75bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      final byte[] b, final int off, final int len) {
76bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    return new InputSupplier<ByteArrayInputStream>() {
771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      @Override
78bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      public ByteArrayInputStream getInput() {
79bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor        return new ByteArrayInputStream(b, off, len);
80bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      }
81bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    };
82bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor  }
83bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor
84bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor  /**
85bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * Writes a byte array to an output stream from the given supplier.
86bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   *
87bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * @param from the bytes to write
88bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * @param to the output supplier
89bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * @throws IOException if an I/O error occurs
90bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   */
91bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor  public static void write(byte[] from,
92bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      OutputSupplier<? extends OutputStream> to) throws IOException {
93bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    Preconditions.checkNotNull(from);
94bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    boolean threw = true;
95bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    OutputStream out = to.getOutput();
96bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    try {
97bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      out.write(from);
98bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      threw = false;
99bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    } finally {
100bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      Closeables.close(out, threw);
101bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    }
102bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor  }
103bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor
104bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor  /**
105bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * Opens input and output streams from the given suppliers, copies all
106bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * bytes from the input to the output, and closes the streams.
107bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   *
108bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * @param from the input factory
109bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * @param to the output factory
110bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * @return the number of bytes copied
111bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * @throws IOException if an I/O error occurs
112bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   */
113bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor  public static long copy(InputSupplier<? extends InputStream> from,
114bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      OutputSupplier<? extends OutputStream> to) throws IOException {
1151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    int successfulOps = 0;
116bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    InputStream in = from.getInput();
117bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    try {
118bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      OutputStream out = to.getOutput();
119bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      try {
120bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor        long count = copy(in, out);
1211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        successfulOps++;
122bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor        return count;
123bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      } finally {
1241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        Closeables.close(out, successfulOps < 1);
1251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        successfulOps++;
126bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      }
127bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    } finally {
1281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      Closeables.close(in, successfulOps < 2);
129bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    }
130bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor  }
131bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor
132bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor  /**
133bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * Opens an input stream from the supplier, copies all bytes from the
134bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * input to the output, and closes the input stream. Does not close
135bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * or flush the output stream.
136bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   *
137bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * @param from the input factory
138bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * @param to the output stream to write to
139bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * @return the number of bytes copied
140bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * @throws IOException if an I/O error occurs
141bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   */
142bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor  public static long copy(InputSupplier<? extends InputStream> from,
143bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      OutputStream to) throws IOException {
144bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    boolean threw = true;
145bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    InputStream in = from.getInput();
146bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    try {
147bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      long count = copy(in, to);
148bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      threw = false;
149bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      return count;
150bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    } finally {
151bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      Closeables.close(in, threw);
152bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    }
153bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor  }
154bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor
155bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor  /**
1561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Opens an output stream from the supplier, copies all bytes from the input
1571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * to the output, and closes the output stream. Does not close or flush the
1581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * output stream.
1591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
1601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @param from the input stream to read from
1611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @param to the output factory
1621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @return the number of bytes copied
1631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @throws IOException if an I/O error occurs
1641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @since 10.0
1651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
1661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public static long copy(InputStream from,
1671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      OutputSupplier<? extends OutputStream> to) throws IOException {
1681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    boolean threw = true;
1691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    OutputStream out = to.getOutput();
1701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    try {
1711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      long count = copy(from, out);
1721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      threw = false;
1731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return count;
1741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } finally {
1751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      Closeables.close(out, threw);
1761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
1771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
1781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
180bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * Copies all bytes from the input stream to the output stream.
181bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * Does not close or flush either stream.
182bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   *
183bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * @param from the input stream to read from
184bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * @param to the output stream to write to
185bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * @return the number of bytes copied
186bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * @throws IOException if an I/O error occurs
187bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   */
188bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor  public static long copy(InputStream from, OutputStream to)
189bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      throws IOException {
190bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    byte[] buf = new byte[BUF_SIZE];
191bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    long total = 0;
192bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    while (true) {
193bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      int r = from.read(buf);
194bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      if (r == -1) {
195bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor        break;
196bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      }
197bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      to.write(buf, 0, r);
198bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      total += r;
199bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    }
200bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    return total;
201bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor  }
202bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor
203bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor  /**
204bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * Copies all bytes from the readable channel to the writable channel.
205bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * Does not close or flush either channel.
206bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   *
207bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * @param from the readable channel to read from
208bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * @param to the writable channel to write to
209bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * @return the number of bytes copied
210bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * @throws IOException if an I/O error occurs
211bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   */
212bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor  public static long copy(ReadableByteChannel from,
213bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      WritableByteChannel to) throws IOException {
214bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    ByteBuffer buf = ByteBuffer.allocate(BUF_SIZE);
215bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    long total = 0;
216bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    while (from.read(buf) != -1) {
217bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      buf.flip();
218bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      while (buf.hasRemaining()) {
219bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor        total += to.write(buf);
220bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      }
221bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      buf.clear();
222bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    }
223bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    return total;
224bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor  }
225bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor
226bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor  /**
227bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * Reads all bytes from an input stream into a byte array.
228bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * Does not close the stream.
229bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   *
230bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * @param in the input stream to read from
231bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * @return a byte array containing all the bytes from the stream
232bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * @throws IOException if an I/O error occurs
233bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   */
234bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor  public static byte[] toByteArray(InputStream in) throws IOException {
235bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    ByteArrayOutputStream out = new ByteArrayOutputStream();
236bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    copy(in, out);
237bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    return out.toByteArray();
238bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor  }
239bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor
240bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor  /**
241bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * Returns the data from a {@link InputStream} factory as a byte array.
242bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   *
243bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * @param supplier the factory
244bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * @throws IOException if an I/O error occurs
245bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   */
246bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor  public static byte[] toByteArray(
247bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      InputSupplier<? extends InputStream> supplier) throws IOException {
248bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    boolean threw = true;
249bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    InputStream in = supplier.getInput();
250bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    try {
251bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      byte[] result = toByteArray(in);
252bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      threw = false;
253bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      return result;
254bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    } finally {
255bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      Closeables.close(in, threw);
256bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    }
257bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor  }
258bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor
259bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor  /**
260bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * Returns a new {@link ByteArrayDataInput} instance to read from the {@code
261bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * bytes} array from the beginning.
262bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   */
263bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor  public static ByteArrayDataInput newDataInput(byte[] bytes) {
264bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    return new ByteArrayDataInputStream(bytes);
265bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor  }
266bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor
267bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor  /**
268bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * Returns a new {@link ByteArrayDataInput} instance to read from the {@code
269bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * bytes} array, starting at the given position.
270bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   *
271bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * @throws IndexOutOfBoundsException if {@code start} is negative or greater
272bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   *     than the length of the array
273bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   */
274bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor  public static ByteArrayDataInput newDataInput(byte[] bytes, int start) {
275bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    Preconditions.checkPositionIndex(start, bytes.length);
276bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    return new ByteArrayDataInputStream(bytes, start);
277bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor  }
278bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor
279bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor  private static class ByteArrayDataInputStream implements ByteArrayDataInput {
280bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    final DataInput input;
281bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor
282bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    ByteArrayDataInputStream(byte[] bytes) {
283bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      this.input = new DataInputStream(new ByteArrayInputStream(bytes));
284bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    }
285bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor
286bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    ByteArrayDataInputStream(byte[] bytes, int start) {
287bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      this.input = new DataInputStream(
288bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor          new ByteArrayInputStream(bytes, start, bytes.length - start));
289bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    }
290bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor
2911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override public void readFully(byte b[]) {
292bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      try {
293bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor        input.readFully(b);
294bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      } catch (IOException e) {
295bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor        throw new IllegalStateException(e);
296bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      }
297bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    }
298bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor
2991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override public void readFully(byte b[], int off, int len) {
300bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      try {
301bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor        input.readFully(b, off, len);
302bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      } catch (IOException e) {
303bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor        throw new IllegalStateException(e);
304bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      }
305bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    }
306bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor
3071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override public int skipBytes(int n) {
308bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      try {
309bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor        return input.skipBytes(n);
310bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      } catch (IOException e) {
311bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor        throw new IllegalStateException(e);
312bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      }
313bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    }
314bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor
3151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override public boolean readBoolean() {
316bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      try {
317bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor        return input.readBoolean();
318bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      } catch (IOException e) {
319bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor        throw new IllegalStateException(e);
320bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      }
321bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    }
322bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor
3231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override public byte readByte() {
324bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      try {
325bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor        return input.readByte();
326bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      } catch (EOFException e) {
327bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor        throw new IllegalStateException(e);
328bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      } catch (IOException impossible) {
329bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor        throw new AssertionError(impossible);
330bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      }
331bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    }
332bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor
3331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override public int readUnsignedByte() {
334bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      try {
335bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor        return input.readUnsignedByte();
336bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      } catch (IOException e) {
337bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor        throw new IllegalStateException(e);
338bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      }
339bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    }
340bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor
3411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override public short readShort() {
342bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      try {
343bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor        return input.readShort();
344bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      } catch (IOException e) {
345bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor        throw new IllegalStateException(e);
346bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      }
347bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    }
348bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor
3491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override public int readUnsignedShort() {
350bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      try {
351bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor        return input.readUnsignedShort();
352bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      } catch (IOException e) {
353bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor        throw new IllegalStateException(e);
354bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      }
355bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    }
356bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor
3571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override public char readChar() {
358bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      try {
359bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor        return input.readChar();
360bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      } catch (IOException e) {
361bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor        throw new IllegalStateException(e);
362bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      }
363bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    }
364bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor
3651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override public int readInt() {
366bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      try {
367bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor        return input.readInt();
368bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      } catch (IOException e) {
369bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor        throw new IllegalStateException(e);
370bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      }
371bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    }
372bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor
3731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override public long readLong() {
374bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      try {
375bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor        return input.readLong();
376bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      } catch (IOException e) {
377bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor        throw new IllegalStateException(e);
378bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      }
379bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    }
380bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor
3811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override public float readFloat() {
382bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      try {
383bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor        return input.readFloat();
384bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      } catch (IOException e) {
385bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor        throw new IllegalStateException(e);
386bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      }
387bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    }
388bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor
3891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override public double readDouble() {
390bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      try {
391bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor        return input.readDouble();
392bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      } catch (IOException e) {
393bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor        throw new IllegalStateException(e);
394bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      }
395bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    }
396bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor
3971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override public String readLine() {
398bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      try {
399bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor        return input.readLine();
400bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      } catch (IOException e) {
401bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor        throw new IllegalStateException(e);
402bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      }
403bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    }
404bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor
4051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override public String readUTF() {
406bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      try {
407bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor        return input.readUTF();
408bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      } catch (IOException e) {
409bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor        throw new IllegalStateException(e);
410bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      }
411bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    }
412bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor  }
413bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor
414bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor  /**
415bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * Returns a new {@link ByteArrayDataOutput} instance with a default size.
416bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   */
417bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor  public static ByteArrayDataOutput newDataOutput() {
418bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    return new ByteArrayDataOutputStream();
419bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor  }
420bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor
421bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor  /**
422bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * Returns a new {@link ByteArrayDataOutput} instance sized to hold
423bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * {@code size} bytes before resizing.
424bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   *
425bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * @throws IllegalArgumentException if {@code size} is negative
426bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   */
427bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor  public static ByteArrayDataOutput newDataOutput(int size) {
428bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    Preconditions.checkArgument(size >= 0, "Invalid size: %s", size);
429bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    return new ByteArrayDataOutputStream(size);
430bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor  }
431bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor
432bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor  @SuppressWarnings("deprecation") // for writeBytes
433bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor  private static class ByteArrayDataOutputStream
434bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      implements ByteArrayDataOutput {
435bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor
436bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    final DataOutput output;
437bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    final ByteArrayOutputStream byteArrayOutputSteam;
438bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor
439bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    ByteArrayDataOutputStream() {
440bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      this(new ByteArrayOutputStream());
441bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    }
442bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor
443bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    ByteArrayDataOutputStream(int size) {
444bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      this(new ByteArrayOutputStream(size));
445bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    }
446bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor
447bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    ByteArrayDataOutputStream(ByteArrayOutputStream byteArrayOutputSteam) {
448bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      this.byteArrayOutputSteam = byteArrayOutputSteam;
449bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      output = new DataOutputStream(byteArrayOutputSteam);
450bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    }
451bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor
4521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override public void write(int b) {
453bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      try {
454bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor        output.write(b);
455bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      } catch (IOException impossible) {
456bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor        throw new AssertionError(impossible);
457bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      }
458bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    }
459bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor
4601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override public void write(byte[] b) {
461bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      try {
462bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor        output.write(b);
463bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      } catch (IOException impossible) {
464bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor        throw new AssertionError(impossible);
465bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      }
466bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    }
467bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor
4681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override public void write(byte[] b, int off, int len) {
469bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      try {
470bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor        output.write(b, off, len);
471bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      } catch (IOException impossible) {
472bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor        throw new AssertionError(impossible);
473bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      }
474bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    }
475bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor
4761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override public void writeBoolean(boolean v) {
477bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      try {
478bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor        output.writeBoolean(v);
479bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      } catch (IOException impossible) {
480bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor        throw new AssertionError(impossible);
481bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      }
482bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    }
483bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor
4841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override public void writeByte(int v) {
485bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      try {
486bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor        output.writeByte(v);
487bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      } catch (IOException impossible) {
488bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor        throw new AssertionError(impossible);
489bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      }
490bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    }
491bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor
4921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override public void writeBytes(String s) {
493bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      try {
494bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor        output.writeBytes(s);
495bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      } catch (IOException impossible) {
496bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor        throw new AssertionError(impossible);
497bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      }
498bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    }
499bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor
5001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override public void writeChar(int v) {
501bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      try {
502bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor        output.writeChar(v);
503bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      } catch (IOException impossible) {
504bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor        throw new AssertionError(impossible);
505bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      }
506bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    }
507bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor
5081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override public void writeChars(String s) {
509bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      try {
510bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor        output.writeChars(s);
511bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      } catch (IOException impossible) {
512bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor        throw new AssertionError(impossible);
513bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      }
514bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    }
515bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor
5161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override public void writeDouble(double v) {
517bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      try {
518bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor        output.writeDouble(v);
519bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      } catch (IOException impossible) {
520bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor        throw new AssertionError(impossible);
521bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      }
522bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    }
523bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor
5241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override public void writeFloat(float v) {
525bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      try {
526bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor        output.writeFloat(v);
527bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      } catch (IOException impossible) {
528bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor        throw new AssertionError(impossible);
529bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      }
530bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    }
531bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor
5321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override public void writeInt(int v) {
533bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      try {
534bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor        output.writeInt(v);
535bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      } catch (IOException impossible) {
536bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor        throw new AssertionError(impossible);
537bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      }
538bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    }
539bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor
5401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override public void writeLong(long v) {
541bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      try {
542bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor        output.writeLong(v);
543bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      } catch (IOException impossible) {
544bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor        throw new AssertionError(impossible);
545bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      }
546bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    }
547bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor
5481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override public void writeShort(int v) {
549bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      try {
550bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor        output.writeShort(v);
551bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      } catch (IOException impossible) {
552bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor        throw new AssertionError(impossible);
553bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      }
554bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    }
555bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor
5561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override public void writeUTF(String s) {
557bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      try {
558bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor        output.writeUTF(s);
559bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      } catch (IOException impossible) {
560bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor        throw new AssertionError(impossible);
561bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      }
562bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    }
563bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor
5641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override public byte[] toByteArray() {
565bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      return byteArrayOutputSteam.toByteArray();
566bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    }
567bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor
568bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor  }
569bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor
5701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  // TODO(chrisn): Not all streams support skipping.
571bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor  /** Returns the length of a supplied input stream, in bytes. */
572bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor  public static long length(InputSupplier<? extends InputStream> supplier)
573bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      throws IOException {
574bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    long count = 0;
575bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    boolean threw = true;
576bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    InputStream in = supplier.getInput();
577bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    try {
578bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      while (true) {
579bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor        // We skip only Integer.MAX_VALUE due to JDK overflow bugs.
580bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor        long amt = in.skip(Integer.MAX_VALUE);
581bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor        if (amt == 0) {
582bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor          if (in.read() == -1) {
583bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor            threw = false;
584bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor            return count;
585bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor          }
586bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor          count++;
587bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor        } else {
588bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor          count += amt;
589bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor        }
590bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      }
591bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    } finally {
592bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      Closeables.close(in, threw);
593bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    }
594bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor  }
595bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor
596bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor  /**
597bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * Returns true if the supplied input streams contain the same bytes.
598bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   *
599bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * @throws IOException if an I/O error occurs
600bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   */
601bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor  public static boolean equal(InputSupplier<? extends InputStream> supplier1,
602bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      InputSupplier<? extends InputStream> supplier2) throws IOException {
603bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    byte[] buf1 = new byte[BUF_SIZE];
604bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    byte[] buf2 = new byte[BUF_SIZE];
605bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor
606bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    boolean threw = true;
607bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    InputStream in1 = supplier1.getInput();
608bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    try {
609bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      InputStream in2 = supplier2.getInput();
610bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      try {
611bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor        while (true) {
612bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor          int read1 = read(in1, buf1, 0, BUF_SIZE);
613bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor          int read2 = read(in2, buf2, 0, BUF_SIZE);
614bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor          if (read1 != read2 || !Arrays.equals(buf1, buf2)) {
615bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor            threw = false;
616bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor            return false;
617bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor          } else if (read1 != BUF_SIZE) {
618bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor            threw = false;
619bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor            return true;
620bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor          }
621bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor        }
622bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      } finally {
623bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor        Closeables.close(in2, threw);
624bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      }
625bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    } finally {
626bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      Closeables.close(in1, threw);
627bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    }
628bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor  }
629bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor
630bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor  /**
631bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * Attempts to read enough bytes from the stream to fill the given byte array,
632bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * with the same behavior as {@link DataInput#readFully(byte[])}.
633bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * Does not close the stream.
634bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   *
635bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * @param in the input stream to read from.
636bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * @param b the buffer into which the data is read.
637bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * @throws EOFException if this stream reaches the end before reading all
638bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   *     the bytes.
639bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * @throws IOException if an I/O error occurs.
640bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   */
641bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor  public static void readFully(InputStream in, byte[] b) throws IOException {
642bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    readFully(in, b, 0, b.length);
643bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor  }
644bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor
645bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor  /**
646bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * Attempts to read {@code len} bytes from the stream into the given array
647bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * starting at {@code off}, with the same behavior as
648bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * {@link DataInput#readFully(byte[], int, int)}. Does not close the
649bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * stream.
650bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   *
651bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * @param in the input stream to read from.
652bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * @param b the buffer into which the data is read.
653bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * @param off an int specifying the offset into the data.
654bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * @param len an int specifying the number of bytes to read.
655bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * @throws EOFException if this stream reaches the end before reading all
656bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   *     the bytes.
657bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * @throws IOException if an I/O error occurs.
658bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   */
659bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor  public static void readFully(InputStream in, byte[] b, int off, int len)
660bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      throws IOException {
661bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    if (read(in, b, off, len) != len) {
662bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      throw new EOFException();
663bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    }
664bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor  }
665bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor
666bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor  /**
667bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * Discards {@code n} bytes of data from the input stream. This method
668bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * will block until the full amount has been skipped. Does not close the
669bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * stream.
670bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   *
671bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * @param in the input stream to read from
672bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * @param n the number of bytes to skip
673bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * @throws EOFException if this stream reaches the end before skipping all
674bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   *     the bytes
675bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * @throws IOException if an I/O error occurs, or the stream does not
676bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   *     support skipping
677bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   */
678bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor  public static void skipFully(InputStream in, long n) throws IOException {
679bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    while (n > 0) {
680bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      long amt = in.skip(n);
681bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      if (amt == 0) {
682bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor        // Force a blocking read to avoid infinite loop
683bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor        if (in.read() == -1) {
684bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor          throw new EOFException();
685bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor        }
686bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor        n--;
687bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      } else {
688bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor        n -= amt;
689bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      }
690bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    }
691bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor  }
692bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor
693bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor  /**
694bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * Process the bytes of a supplied stream
695bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   *
696bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * @param supplier the input stream factory
697bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * @param processor the object to which to pass the bytes of the stream
698bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * @return the result of the byte processor
699bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * @throws IOException if an I/O error occurs
700bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   */
701bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor  public static <T> T readBytes(InputSupplier<? extends InputStream> supplier,
702bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      ByteProcessor<T> processor) throws IOException {
703bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    byte[] buf = new byte[BUF_SIZE];
704bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    boolean threw = true;
705bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    InputStream in = supplier.getInput();
706bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    try {
707bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      int amt;
708bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      do {
709bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor        amt = in.read(buf);
710bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor        if (amt == -1) {
711bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor          threw = false;
712bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor          break;
713bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor        }
714bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      } while (processor.processBytes(buf, 0, amt));
715bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      return processor.getResult();
716bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    } finally {
717bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      Closeables.close(in, threw);
718bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    }
719bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor  }
720bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor
721bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor  /**
722bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * Computes and returns the checksum value for a supplied input stream.
723bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * The checksum object is reset when this method returns successfully.
724bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   *
725bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * @param supplier the input stream factory
726bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * @param checksum the checksum object
727bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * @return the result of {@link Checksum#getValue} after updating the
728bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   *     checksum object with all of the bytes in the stream
729bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * @throws IOException if an I/O error occurs
730bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   */
731bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor  public static long getChecksum(InputSupplier<? extends InputStream> supplier,
732bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      final Checksum checksum) throws IOException {
733bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    return readBytes(supplier, new ByteProcessor<Long>() {
7341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      @Override
735bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      public boolean processBytes(byte[] buf, int off, int len) {
736bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor        checksum.update(buf, off, len);
737bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor        return true;
738bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      }
739bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor
7401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      @Override
741bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      public Long getResult() {
742bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor        long result = checksum.getValue();
743bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor        checksum.reset();
744bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor        return result;
745bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      }
746bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    });
747bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor  }
748bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor
749bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor  /**
750bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * Computes and returns the digest value for a supplied input stream.
751bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * The digest object is reset when this method returns successfully.
752bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   *
753bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * @param supplier the input stream factory
754bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * @param md the digest object
755bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * @return the result of {@link MessageDigest#digest()} after updating the
756bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   *     digest object with all of the bytes in the stream
757bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * @throws IOException if an I/O error occurs
758bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   */
759bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor  public static byte[] getDigest(InputSupplier<? extends InputStream> supplier,
760bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      final MessageDigest md) throws IOException {
761bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    return readBytes(supplier, new ByteProcessor<byte[]>() {
7621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      @Override
763bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      public boolean processBytes(byte[] buf, int off, int len) {
764bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor        md.update(buf, off, len);
765bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor        return true;
766bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      }
767bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor
7681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      @Override
769bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      public byte[] getResult() {
770bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor        return md.digest();
771bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      }
772bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    });
773bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor  }
774bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor
775bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor  /**
776bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * Reads some bytes from an input stream and stores them into the buffer array
777bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * {@code b}. This method blocks until {@code len} bytes of input data have
778bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * been read into the array, or end of file is detected. The number of bytes
779bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * read is returned, possibly zero. Does not close the stream.
780bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   *
781bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * <p>A caller can detect EOF if the number of bytes read is less than
782bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * {@code len}. All subsequent calls on the same stream will return zero.
783bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   *
784bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * <p>If {@code b} is null, a {@code NullPointerException} is thrown. If
785bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * {@code off} is negative, or {@code len} is negative, or {@code off+len} is
786bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * greater than the length of the array {@code b}, then an
787bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * {@code IndexOutOfBoundsException} is thrown. If {@code len} is zero, then
788bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * no bytes are read. Otherwise, the first byte read is stored into element
789bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * {@code b[off]}, the next one into {@code b[off+1]}, and so on. The number
790bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * of bytes read is, at most, equal to {@code len}.
791bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   *
792bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * @param in the input stream to read from
793bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * @param b the buffer into which the data is read
794bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * @param off an int specifying the offset into the data
795bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * @param len an int specifying the number of bytes to read
796bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * @return the number of bytes read
797bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * @throws IOException if an I/O error occurs
798bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   */
799bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor  public static int read(InputStream in, byte[] b, int off, int len)
800bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      throws IOException {
801bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    if (len < 0) {
802bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      throw new IndexOutOfBoundsException("len is negative");
803bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    }
804bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    int total = 0;
805bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    while (total < len) {
806bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      int result = in.read(b, off + total, len - total);
807bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      if (result == -1) {
808bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor        break;
809bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      }
810bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      total += result;
811bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    }
812bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    return total;
813bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor  }
814bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor
815bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor  /**
816bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * Returns an {@link InputSupplier} that returns input streams from the
817bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * an underlying supplier, where each stream starts at the given
818bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * offset and is limited to the specified number of bytes.
819bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   *
820bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * @param supplier the supplier from which to get the raw streams
821bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * @param offset the offset in bytes into the underlying stream where
822bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   *     the returned streams will start
823bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * @param length the maximum length of the returned streams
824bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * @throws IllegalArgumentException if offset or length are negative
825bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   */
826bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor  public static InputSupplier<InputStream> slice(
827bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      final InputSupplier<? extends InputStream> supplier,
828bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      final long offset,
829bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      final long length) {
830bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    Preconditions.checkNotNull(supplier);
831bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    Preconditions.checkArgument(offset >= 0, "offset is negative");
832bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    Preconditions.checkArgument(length >= 0, "length is negative");
833bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    return new InputSupplier<InputStream>() {
8341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      @Override public InputStream getInput() throws IOException {
835bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor        InputStream in = supplier.getInput();
836bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor        if (offset > 0) {
837bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor          try {
838bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor            skipFully(in, offset);
839bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor          } catch (IOException e) {
840bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor            Closeables.closeQuietly(in);
841bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor            throw e;
842bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor          }
843bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor        }
844bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor        return new LimitInputStream(in, length);
845bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      }
846bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    };
847bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor  }
848bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor
849bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor  /**
850bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * Joins multiple {@link InputStream} suppliers into a single supplier.
851bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * Streams returned from the supplier will contain the concatenated data from
852bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * the streams of the underlying suppliers.
853bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   *
854bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * <p>Only one underlying input stream will be open at a time. Closing the
855bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * joined stream will close the open underlying stream.
856bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   *
857bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * <p>Reading from the joined stream will throw a {@link NullPointerException}
858bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * if any of the suppliers are null or return null.
859bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   *
860bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * @param suppliers the suppliers to concatenate
861bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * @return a supplier that will return a stream containing the concatenated
862bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   *     stream data
863bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   */
864bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor  public static InputSupplier<InputStream> join(
8651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      final Iterable<? extends InputSupplier<? extends InputStream>> suppliers) {
866bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    return new InputSupplier<InputStream>() {
8671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      @Override public InputStream getInput() throws IOException {
868bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor        return new MultiInputStream(suppliers.iterator());
869bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      }
870bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    };
871bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor  }
872bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor
873bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor  /** Varargs form of {@link #join(Iterable)}. */
874bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor  public static InputSupplier<InputStream> join(
875bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      InputSupplier<? extends InputStream>... suppliers) {
876bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    return join(Arrays.asList(suppliers));
877bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor  }
878bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor}
879