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;
024
025import java.io.ByteArrayInputStream;
026import java.io.ByteArrayOutputStream;
027import java.io.DataInput;
028import java.io.DataInputStream;
029import java.io.DataOutput;
030import java.io.DataOutputStream;
031import java.io.EOFException;
032import java.io.FilterInputStream;
033import java.io.IOException;
034import java.io.InputStream;
035import java.io.OutputStream;
036import java.nio.ByteBuffer;
037import java.nio.channels.FileChannel;
038import java.nio.channels.ReadableByteChannel;
039import java.nio.channels.WritableByteChannel;
040import java.util.Arrays;
041
042/**
043 * Provides utility methods for working with byte arrays and I/O streams.
044 *
045 * @author Chris Nokleberg
046 * @author Colin Decker
047 * @since 1.0
048 */
049@Beta
050public final class ByteStreams {
051
052  /**
053   * Default size of buffers allocated for copies.
054   */
055  static final int BUF_SIZE = 8192;
056
057  /**
058   * A buffer for skipping bytes in an input stream. Only written to and never read, so actual
059   * contents don't matter.
060   */
061  static final byte[] skipBuffer = new byte[BUF_SIZE];
062
063  /**
064   * There are three methods to implement {@link FileChannel#transferTo(long, long,
065   *  WritableByteChannel)}:
066   *
067   * <ol>
068   * <li> Use sendfile(2) or equivalent. Requires that both the input channel and the output channel
069   *    have their own file descriptors. Generally this only happens when both channels are files or
070   *    sockets. This performs zero copies - the bytes never enter userspace.</li>
071   * <li> Use mmap(2) or equivalent. Requires that either the input channel or the output channel
072   *    have file descriptors. Bytes are copied from the file into a kernel buffer, then directly
073   *    into the other buffer (userspace). Note that if the file is very large, a naive
074   *    implementation will effectively put the whole file in memory. On many systems with paging
075   *    and virtual memory, this is not a problem - because it is mapped read-only, the kernel can
076   *    always page it to disk "for free". However, on systems where killing processes happens all
077   *    the time in normal conditions (i.e., android) the OS must make a tradeoff between paging
078   *    memory and killing other processes - so allocating a gigantic buffer and then sequentially
079   *    accessing it could result in other processes dying. This is solvable via madvise(2), but
080   *    that obviously doesn't exist in java.</li>
081   * <li> Ordinary copy. Kernel copies bytes into a kernel buffer, from a kernel buffer into a
082   *    userspace buffer (byte[] or ByteBuffer), then copies them from that buffer into the
083   *    destination channel.</li>
084   * </ol>
085   *
086   * This value is intended to be large enough to make the overhead of system calls negligible,
087   * without being so large that it causes problems for systems with atypical memory management if
088   * approaches 2 or 3 are used.
089   */
090  private static final int ZERO_COPY_CHUNK_SIZE = 512 * 1024;
091
092  private ByteStreams() {}
093
094  /**
095   * Copies all bytes from the input stream to the output stream.
096   * Does not close or flush either stream.
097   *
098   * @param from the input stream to read from
099   * @param to the output stream to write to
100   * @return the number of bytes copied
101   * @throws IOException if an I/O error occurs
102   */
103  public static long copy(InputStream from, OutputStream to)
104      throws IOException {
105    checkNotNull(from);
106    checkNotNull(to);
107    byte[] buf = new byte[BUF_SIZE];
108    long total = 0;
109    while (true) {
110      int r = from.read(buf);
111      if (r == -1) {
112        break;
113      }
114      to.write(buf, 0, r);
115      total += r;
116    }
117    return total;
118  }
119
120  /**
121   * Copies all bytes from the readable channel to the writable channel.
122   * Does not close or flush either channel.
123   *
124   * @param from the readable channel to read from
125   * @param to the writable channel to write to
126   * @return the number of bytes copied
127   * @throws IOException if an I/O error occurs
128   */
129  public static long copy(ReadableByteChannel from,
130      WritableByteChannel to) throws IOException {
131    checkNotNull(from);
132    checkNotNull(to);
133    if (from instanceof FileChannel) {
134      FileChannel sourceChannel = (FileChannel) from;
135      long oldPosition = sourceChannel.position();
136      long position = oldPosition;
137      long copied;
138      do {
139        copied = sourceChannel.transferTo(position, ZERO_COPY_CHUNK_SIZE, to);
140        position += copied;
141        sourceChannel.position(position);
142      } while (copied > 0 || position < sourceChannel.size());
143      return position - oldPosition;
144    }
145
146    ByteBuffer buf = ByteBuffer.allocate(BUF_SIZE);
147    long total = 0;
148    while (from.read(buf) != -1) {
149      buf.flip();
150      while (buf.hasRemaining()) {
151        total += to.write(buf);
152      }
153      buf.clear();
154    }
155    return total;
156  }
157
158  /**
159   * Reads all bytes from an input stream into a byte array.
160   * Does not close the stream.
161   *
162   * @param in the input stream to read from
163   * @return a byte array containing all the bytes from the stream
164   * @throws IOException if an I/O error occurs
165   */
166  public static byte[] toByteArray(InputStream in) throws IOException {
167    ByteArrayOutputStream out = new ByteArrayOutputStream();
168    copy(in, out);
169    return out.toByteArray();
170  }
171
172  /**
173   * Reads all bytes from an input stream into a byte array. The given
174   * expected size is used to create an initial byte array, but if the actual
175   * number of bytes read from the stream differs, the correct result will be
176   * returned anyway.
177   */
178  static byte[] toByteArray(
179      InputStream in, int expectedSize) throws IOException {
180    byte[] bytes = new byte[expectedSize];
181    int remaining = expectedSize;
182
183    while (remaining > 0) {
184      int off = expectedSize - remaining;
185      int read = in.read(bytes, off, remaining);
186      if (read == -1) {
187        // end of stream before reading expectedSize bytes
188        // just return the bytes read so far
189        return Arrays.copyOf(bytes, off);
190      }
191      remaining -= read;
192    }
193
194    // bytes is now full
195    int b = in.read();
196    if (b == -1) {
197      return bytes;
198    }
199
200    // the stream was longer, so read the rest normally
201    FastByteArrayOutputStream out = new FastByteArrayOutputStream();
202    out.write(b); // write the byte we read when testing for end of stream
203    copy(in, out);
204
205    byte[] result = new byte[bytes.length + out.size()];
206    System.arraycopy(bytes, 0, result, 0, bytes.length);
207    out.writeTo(result, bytes.length);
208    return result;
209  }
210
211  /**
212   * BAOS that provides limited access to its internal byte array.
213   */
214  private static final class FastByteArrayOutputStream
215      extends ByteArrayOutputStream {
216    /**
217     * Writes the contents of the internal buffer to the given array starting
218     * at the given offset. Assumes the array has space to hold count bytes.
219     */
220    void writeTo(byte[] b, int off) {
221      System.arraycopy(buf, 0, b, off, count);
222    }
223  }
224
225  /**
226   * Returns a new {@link ByteArrayDataInput} instance to read from the {@code
227   * bytes} array from the beginning.
228   */
229  public static ByteArrayDataInput newDataInput(byte[] bytes) {
230    return newDataInput(new ByteArrayInputStream(bytes));
231  }
232
233  /**
234   * Returns a new {@link ByteArrayDataInput} instance to read from the {@code
235   * bytes} array, starting at the given position.
236   *
237   * @throws IndexOutOfBoundsException if {@code start} is negative or greater
238   *     than the length of the array
239   */
240  public static ByteArrayDataInput newDataInput(byte[] bytes, int start) {
241    checkPositionIndex(start, bytes.length);
242    return newDataInput(
243        new ByteArrayInputStream(bytes, start, bytes.length - start));
244  }
245
246  /**
247   * Returns a new {@link ByteArrayDataInput} instance to read from the given
248   * {@code ByteArrayInputStream}. The given input stream is not reset before
249   * being read from by the returned {@code ByteArrayDataInput}.
250   *
251   * @since 17.0
252   */
253  public static ByteArrayDataInput newDataInput(
254      ByteArrayInputStream byteArrayInputStream) {
255    return new ByteArrayDataInputStream(checkNotNull(byteArrayInputStream));
256  }
257
258  private static class ByteArrayDataInputStream implements ByteArrayDataInput {
259    final DataInput input;
260
261    ByteArrayDataInputStream(ByteArrayInputStream byteArrayInputStream) {
262      this.input = new DataInputStream(byteArrayInputStream);
263    }
264
265    @Override public void readFully(byte b[]) {
266      try {
267        input.readFully(b);
268      } catch (IOException e) {
269        throw new IllegalStateException(e);
270      }
271    }
272
273    @Override public void readFully(byte b[], int off, int len) {
274      try {
275        input.readFully(b, off, len);
276      } catch (IOException e) {
277        throw new IllegalStateException(e);
278      }
279    }
280
281    @Override public int skipBytes(int n) {
282      try {
283        return input.skipBytes(n);
284      } catch (IOException e) {
285        throw new IllegalStateException(e);
286      }
287    }
288
289    @Override public boolean readBoolean() {
290      try {
291        return input.readBoolean();
292      } catch (IOException e) {
293        throw new IllegalStateException(e);
294      }
295    }
296
297    @Override public byte readByte() {
298      try {
299        return input.readByte();
300      } catch (EOFException e) {
301        throw new IllegalStateException(e);
302      } catch (IOException impossible) {
303        throw new AssertionError(impossible);
304      }
305    }
306
307    @Override public int readUnsignedByte() {
308      try {
309        return input.readUnsignedByte();
310      } catch (IOException e) {
311        throw new IllegalStateException(e);
312      }
313    }
314
315    @Override public short readShort() {
316      try {
317        return input.readShort();
318      } catch (IOException e) {
319        throw new IllegalStateException(e);
320      }
321    }
322
323    @Override public int readUnsignedShort() {
324      try {
325        return input.readUnsignedShort();
326      } catch (IOException e) {
327        throw new IllegalStateException(e);
328      }
329    }
330
331    @Override public char readChar() {
332      try {
333        return input.readChar();
334      } catch (IOException e) {
335        throw new IllegalStateException(e);
336      }
337    }
338
339    @Override public int readInt() {
340      try {
341        return input.readInt();
342      } catch (IOException e) {
343        throw new IllegalStateException(e);
344      }
345    }
346
347    @Override public long readLong() {
348      try {
349        return input.readLong();
350      } catch (IOException e) {
351        throw new IllegalStateException(e);
352      }
353    }
354
355    @Override public float readFloat() {
356      try {
357        return input.readFloat();
358      } catch (IOException e) {
359        throw new IllegalStateException(e);
360      }
361    }
362
363    @Override public double readDouble() {
364      try {
365        return input.readDouble();
366      } catch (IOException e) {
367        throw new IllegalStateException(e);
368      }
369    }
370
371    @Override public String readLine() {
372      try {
373        return input.readLine();
374      } catch (IOException e) {
375        throw new IllegalStateException(e);
376      }
377    }
378
379    @Override public String readUTF() {
380      try {
381        return input.readUTF();
382      } catch (IOException e) {
383        throw new IllegalStateException(e);
384      }
385    }
386  }
387
388  /**
389   * Returns a new {@link ByteArrayDataOutput} instance with a default size.
390   */
391  public static ByteArrayDataOutput newDataOutput() {
392    return newDataOutput(new ByteArrayOutputStream());
393  }
394
395  /**
396   * Returns a new {@link ByteArrayDataOutput} instance sized to hold
397   * {@code size} bytes before resizing.
398   *
399   * @throws IllegalArgumentException if {@code size} is negative
400   */
401  public static ByteArrayDataOutput newDataOutput(int size) {
402    // When called at high frequency, boxing size generates too much garbage,
403    // so avoid doing that if we can.
404    if (size < 0) {
405      throw new IllegalArgumentException(String.format("Invalid size: %s", size));
406    }
407    return newDataOutput(new ByteArrayOutputStream(size));
408  }
409
410  /**
411   * Returns a new {@link ByteArrayDataOutput} instance which writes to the
412   * given {@code ByteArrayOutputStream}. The given output stream is not reset
413   * before being written to by the returned {@code ByteArrayDataOutput} and
414   * new data will be appended to any existing content.
415   *
416   * <p>Note that if the given output stream was not empty or is modified after
417   * the {@code ByteArrayDataOutput} is created, the contract for
418   * {@link ByteArrayDataOutput#toByteArray} will not be honored (the bytes
419   * returned in the byte array may not be exactly what was written via calls to
420   * {@code ByteArrayDataOutput}).
421   *
422   * @since 17.0
423   */
424  public static ByteArrayDataOutput newDataOutput(
425      ByteArrayOutputStream byteArrayOutputSteam) {
426    return new ByteArrayDataOutputStream(checkNotNull(byteArrayOutputSteam));
427  }
428
429  @SuppressWarnings("deprecation") // for writeBytes
430  private static class ByteArrayDataOutputStream
431      implements ByteArrayDataOutput {
432
433    final DataOutput output;
434    final ByteArrayOutputStream byteArrayOutputSteam;
435
436    ByteArrayDataOutputStream(ByteArrayOutputStream byteArrayOutputSteam) {
437      this.byteArrayOutputSteam = byteArrayOutputSteam;
438      output = new DataOutputStream(byteArrayOutputSteam);
439    }
440
441    @Override public void write(int b) {
442      try {
443        output.write(b);
444      } catch (IOException impossible) {
445        throw new AssertionError(impossible);
446      }
447    }
448
449    @Override public void write(byte[] b) {
450      try {
451        output.write(b);
452      } catch (IOException impossible) {
453        throw new AssertionError(impossible);
454      }
455    }
456
457    @Override public void write(byte[] b, int off, int len) {
458      try {
459        output.write(b, off, len);
460      } catch (IOException impossible) {
461        throw new AssertionError(impossible);
462      }
463    }
464
465    @Override public void writeBoolean(boolean v) {
466      try {
467        output.writeBoolean(v);
468      } catch (IOException impossible) {
469        throw new AssertionError(impossible);
470      }
471    }
472
473    @Override public void writeByte(int v) {
474      try {
475        output.writeByte(v);
476      } catch (IOException impossible) {
477        throw new AssertionError(impossible);
478      }
479    }
480
481    @Override public void writeBytes(String s) {
482      try {
483        output.writeBytes(s);
484      } catch (IOException impossible) {
485        throw new AssertionError(impossible);
486      }
487    }
488
489    @Override public void writeChar(int v) {
490      try {
491        output.writeChar(v);
492      } catch (IOException impossible) {
493        throw new AssertionError(impossible);
494      }
495    }
496
497    @Override public void writeChars(String s) {
498      try {
499        output.writeChars(s);
500      } catch (IOException impossible) {
501        throw new AssertionError(impossible);
502      }
503    }
504
505    @Override public void writeDouble(double v) {
506      try {
507        output.writeDouble(v);
508      } catch (IOException impossible) {
509        throw new AssertionError(impossible);
510      }
511    }
512
513    @Override public void writeFloat(float v) {
514      try {
515        output.writeFloat(v);
516      } catch (IOException impossible) {
517        throw new AssertionError(impossible);
518      }
519    }
520
521    @Override public void writeInt(int v) {
522      try {
523        output.writeInt(v);
524      } catch (IOException impossible) {
525        throw new AssertionError(impossible);
526      }
527    }
528
529    @Override public void writeLong(long v) {
530      try {
531        output.writeLong(v);
532      } catch (IOException impossible) {
533        throw new AssertionError(impossible);
534      }
535    }
536
537    @Override public void writeShort(int v) {
538      try {
539        output.writeShort(v);
540      } catch (IOException impossible) {
541        throw new AssertionError(impossible);
542      }
543    }
544
545    @Override public void writeUTF(String s) {
546      try {
547        output.writeUTF(s);
548      } catch (IOException impossible) {
549        throw new AssertionError(impossible);
550      }
551    }
552
553    @Override public byte[] toByteArray() {
554      return byteArrayOutputSteam.toByteArray();
555    }
556  }
557
558  private static final OutputStream NULL_OUTPUT_STREAM =
559      new OutputStream() {
560        /** Discards the specified byte. */
561        @Override public void write(int b) {
562        }
563        /** Discards the specified byte array. */
564        @Override public void write(byte[] b) {
565          checkNotNull(b);
566        }
567        /** Discards the specified byte array. */
568        @Override public void write(byte[] b, int off, int len) {
569          checkNotNull(b);
570        }
571
572        @Override
573        public String toString() {
574          return "ByteStreams.nullOutputStream()";
575        }
576      };
577
578  /**
579   * Returns an {@link OutputStream} that simply discards written bytes.
580   *
581   * @since 14.0 (since 1.0 as com.google.common.io.NullOutputStream)
582   */
583  public static OutputStream nullOutputStream() {
584    return NULL_OUTPUT_STREAM;
585  }
586
587  /**
588   * Wraps a {@link InputStream}, limiting the number of bytes which can be
589   * read.
590   *
591   * @param in the input stream to be wrapped
592   * @param limit the maximum number of bytes to be read
593   * @return a length-limited {@link InputStream}
594   * @since 14.0 (since 1.0 as com.google.common.io.LimitInputStream)
595   */
596  public static InputStream limit(InputStream in, long limit) {
597    return new LimitedInputStream(in, limit);
598  }
599
600  private static final class LimitedInputStream extends FilterInputStream {
601
602    private long left;
603    private long mark = -1;
604
605    LimitedInputStream(InputStream in, long limit) {
606      super(in);
607      checkNotNull(in);
608      checkArgument(limit >= 0, "limit must be non-negative");
609      left = limit;
610    }
611
612    @Override public int available() throws IOException {
613      return (int) Math.min(in.available(), left);
614    }
615
616    // it's okay to mark even if mark isn't supported, as reset won't work
617    @Override public synchronized void mark(int readLimit) {
618      in.mark(readLimit);
619      mark = left;
620    }
621
622    @Override public int read() throws IOException {
623      if (left == 0) {
624        return -1;
625      }
626
627      int result = in.read();
628      if (result != -1) {
629        --left;
630      }
631      return result;
632    }
633
634    @Override public int read(byte[] b, int off, int len) throws IOException {
635      if (left == 0) {
636        return -1;
637      }
638
639      len = (int) Math.min(len, left);
640      int result = in.read(b, off, len);
641      if (result != -1) {
642        left -= result;
643      }
644      return result;
645    }
646
647    @Override public synchronized void reset() throws IOException {
648      if (!in.markSupported()) {
649        throw new IOException("Mark not supported");
650      }
651      if (mark == -1) {
652        throw new IOException("Mark not set");
653      }
654
655      in.reset();
656      left = mark;
657    }
658
659    @Override public long skip(long n) throws IOException {
660      n = Math.min(n, left);
661      long skipped = in.skip(n);
662      left -= skipped;
663      return skipped;
664    }
665  }
666
667  /**
668   * Attempts to read enough bytes from the stream to fill the given byte array,
669   * with the same behavior as {@link DataInput#readFully(byte[])}.
670   * Does not close the stream.
671   *
672   * @param in the input stream to read from.
673   * @param b the buffer into which the data is read.
674   * @throws EOFException if this stream reaches the end before reading all
675   *     the bytes.
676   * @throws IOException if an I/O error occurs.
677   */
678  public static void readFully(InputStream in, byte[] b) throws IOException {
679    readFully(in, b, 0, b.length);
680  }
681
682  /**
683   * Attempts to read {@code len} bytes from the stream into the given array
684   * starting at {@code off}, with the same behavior as
685   * {@link DataInput#readFully(byte[], int, int)}. Does not close the
686   * stream.
687   *
688   * @param in the input stream to read from.
689   * @param b the buffer into which the data is read.
690   * @param off an int specifying the offset into the data.
691   * @param len an int specifying the number of bytes to read.
692   * @throws EOFException if this stream reaches the end before reading all
693   *     the bytes.
694   * @throws IOException if an I/O error occurs.
695   */
696  public static void readFully(
697      InputStream in, byte[] b, int off, int len) throws IOException {
698    int read = read(in, b, off, len);
699    if (read != len) {
700      throw new EOFException("reached end of stream after reading "
701          + read + " bytes; " + len + " bytes expected");
702    }
703  }
704
705  /**
706   * Discards {@code n} bytes of data from the input stream. This method
707   * will block until the full amount has been skipped. Does not close the
708   * stream.
709   *
710   * @param in the input stream to read from
711   * @param n the number of bytes to skip
712   * @throws EOFException if this stream reaches the end before skipping all
713   *     the bytes
714   * @throws IOException if an I/O error occurs, or the stream does not
715   *     support skipping
716   */
717  public static void skipFully(InputStream in, long n) throws IOException {
718    long skipped = skipUpTo(in, n);
719    if (skipped < n) {
720      throw new EOFException("reached end of stream after skipping "
721          + skipped + " bytes; " + n + " bytes expected");
722    }
723  }
724
725  /**
726   * Discards up to {@code n} bytes of data from the input stream. This method
727   * will block until either the full amount has been skipped or until the end
728   * of the stream is reached, whichever happens first. Returns the total number
729   * of bytes skipped.
730   */
731  static long skipUpTo(InputStream in, final long n) throws IOException {
732    long totalSkipped = 0;
733
734    while (totalSkipped < n) {
735      long remaining = n - totalSkipped;
736
737      long skipped = skipSafely(in, remaining);
738
739      if (skipped == 0) {
740        // Do a buffered read since skipSafely could return 0 repeatedly, for example if
741        // in.available() always returns 0 (the default).
742        int skip = (int) Math.min(remaining, skipBuffer.length);
743        if ((skipped = in.read(skipBuffer, 0, skip)) == -1) {
744          // Reached EOF
745          break;
746        }
747      }
748
749      totalSkipped += skipped;
750    }
751
752    return totalSkipped;
753  }
754
755  /**
756   * Attempts to skip up to {@code n} bytes from the given input stream, but not more than
757   * {@code in.available()} bytes. This prevents {@code FileInputStream} from skipping more bytes
758   * than actually remain in the file, something that it
759   * {@linkplain FileInputStream#skip(long) specifies} it can do in its Javadoc despite the fact
760   * that it is violating the contract of {@code InputStream.skip()}.
761   */
762  private static long skipSafely(InputStream in, long n) throws IOException {
763    int available = in.available();
764    return available == 0 ? 0 : in.skip(Math.min(available, n));
765  }
766
767  /**
768   * Process the bytes of the given input stream using the given processor.
769   *
770   * @param input the input stream to process
771   * @param processor the object to which to pass the bytes of the stream
772   * @return the result of the byte processor
773   * @throws IOException if an I/O error occurs
774   * @since 14.0
775   */
776  public static <T> T readBytes(
777      InputStream input, ByteProcessor<T> processor) throws IOException {
778    checkNotNull(input);
779    checkNotNull(processor);
780
781    byte[] buf = new byte[BUF_SIZE];
782    int read;
783    do {
784      read = input.read(buf);
785    } while (read != -1 && processor.processBytes(buf, 0, read));
786    return processor.getResult();
787  }
788
789  /**
790   * Reads some bytes from an input stream and stores them into the buffer array
791   * {@code b}. This method blocks until {@code len} bytes of input data have
792   * been read into the array, or end of file is detected. The number of bytes
793   * read is returned, possibly zero. Does not close the stream.
794   *
795   * <p>A caller can detect EOF if the number of bytes read is less than
796   * {@code len}. All subsequent calls on the same stream will return zero.
797   *
798   * <p>If {@code b} is null, a {@code NullPointerException} is thrown. If
799   * {@code off} is negative, or {@code len} is negative, or {@code off+len} is
800   * greater than the length of the array {@code b}, then an
801   * {@code IndexOutOfBoundsException} is thrown. If {@code len} is zero, then
802   * no bytes are read. Otherwise, the first byte read is stored into element
803   * {@code b[off]}, the next one into {@code b[off+1]}, and so on. The number
804   * of bytes read is, at most, equal to {@code len}.
805   *
806   * @param in the input stream to read from
807   * @param b the buffer into which the data is read
808   * @param off an int specifying the offset into the data
809   * @param len an int specifying the number of bytes to read
810   * @return the number of bytes read
811   * @throws IOException if an I/O error occurs
812   */
813  public static int read(InputStream in, byte[] b, int off, int len)
814      throws IOException {
815    checkNotNull(in);
816    checkNotNull(b);
817    if (len < 0) {
818      throw new IndexOutOfBoundsException("len is negative");
819    }
820    int total = 0;
821    while (total < len) {
822      int result = in.read(b, off + total, len - total);
823      if (result == -1) {
824        break;
825      }
826      total += result;
827    }
828    return total;
829  }
830}