001/*
002 * Copyright (C) 2007 The Guava Authors
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
005 * in compliance with the License. You may obtain a copy of the License at
006 *
007 * http://www.apache.org/licenses/LICENSE-2.0
008 *
009 * Unless required by applicable law or agreed to in writing, software distributed under the License
010 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
011 * or implied. See the License for the specific language governing permissions and limitations under
012 * the License.
013 */
014
015package com.google.common.io;
016
017import static com.google.common.base.Preconditions.checkArgument;
018import static com.google.common.base.Preconditions.checkNotNull;
019import static com.google.common.base.Preconditions.checkPositionIndex;
020import static com.google.common.base.Preconditions.checkPositionIndexes;
021import static java.lang.Math.max;
022import static java.lang.Math.min;
023
024import com.google.common.annotations.GwtIncompatible;
025import com.google.common.annotations.J2ktIncompatible;
026import com.google.common.math.IntMath;
027import com.google.errorprone.annotations.CanIgnoreReturnValue;
028import java.io.ByteArrayInputStream;
029import java.io.ByteArrayOutputStream;
030import java.io.DataInput;
031import java.io.DataInputStream;
032import java.io.DataOutput;
033import java.io.DataOutputStream;
034import java.io.EOFException;
035import java.io.FilterInputStream;
036import java.io.IOException;
037import java.io.InputStream;
038import java.io.OutputStream;
039import java.nio.ByteBuffer;
040import java.nio.channels.FileChannel;
041import java.nio.channels.ReadableByteChannel;
042import java.nio.channels.WritableByteChannel;
043import java.util.ArrayDeque;
044import java.util.Arrays;
045import java.util.Queue;
046import javax.annotation.CheckForNull;
047import org.checkerframework.checker.nullness.qual.Nullable;
048
049/**
050 * Provides utility methods for working with byte arrays and I/O streams.
051 *
052 * @author Chris Nokleberg
053 * @author Colin Decker
054 * @since 1.0
055 */
056@J2ktIncompatible
057@GwtIncompatible
058public final class ByteStreams {
059
060  private static final int BUFFER_SIZE = 8192;
061
062  /** Creates a new byte array for buffering reads or writes. */
063  static byte[] createBuffer() {
064    return new byte[BUFFER_SIZE];
065  }
066
067  /**
068   * There are three methods to implement {@link FileChannel#transferTo(long, long,
069   * WritableByteChannel)}:
070   *
071   * <ol>
072   *   <li>Use sendfile(2) or equivalent. Requires that both the input channel and the output
073   *       channel have their own file descriptors. Generally this only happens when both channels
074   *       are files or sockets. This performs zero copies - the bytes never enter userspace.
075   *   <li>Use mmap(2) or equivalent. Requires that either the input channel or the output channel
076   *       have file descriptors. Bytes are copied from the file into a kernel buffer, then directly
077   *       into the other buffer (userspace). Note that if the file is very large, a naive
078   *       implementation will effectively put the whole file in memory. On many systems with paging
079   *       and virtual memory, this is not a problem - because it is mapped read-only, the kernel
080   *       can always page it to disk "for free". However, on systems where killing processes
081   *       happens all the time in normal conditions (i.e., android) the OS must make a tradeoff
082   *       between paging memory and killing other processes - so allocating a gigantic buffer and
083   *       then sequentially accessing it could result in other processes dying. This is solvable
084   *       via madvise(2), but that obviously doesn't exist in java.
085   *   <li>Ordinary copy. Kernel copies bytes into a kernel buffer, from a kernel buffer into a
086   *       userspace buffer (byte[] or ByteBuffer), then copies them from that buffer into the
087   *       destination channel.
088   * </ol>
089   *
090   * This value is intended to be large enough to make the overhead of system calls negligible,
091   * without being so large that it causes problems for systems with atypical memory management if
092   * approaches 2 or 3 are used.
093   */
094  private static final int ZERO_COPY_CHUNK_SIZE = 512 * 1024;
095
096  private ByteStreams() {}
097
098  /**
099   * Copies all bytes from the input stream to the output stream. Does not close or flush either
100   * stream.
101   *
102   * <p><b>Java 9 users and later:</b> this method should be treated as deprecated; use the
103   * equivalent {@link InputStream#transferTo} method instead.
104   *
105   * @param from the input stream to read from
106   * @param to the output stream to write to
107   * @return the number of bytes copied
108   * @throws IOException if an I/O error occurs
109   */
110  @CanIgnoreReturnValue
111  public static long copy(InputStream from, OutputStream to) throws IOException {
112    checkNotNull(from);
113    checkNotNull(to);
114    byte[] buf = createBuffer();
115    long total = 0;
116    while (true) {
117      int r = from.read(buf);
118      if (r == -1) {
119        break;
120      }
121      to.write(buf, 0, r);
122      total += r;
123    }
124    return total;
125  }
126
127  /**
128   * Copies all bytes from the readable channel to the writable channel. Does not close or flush
129   * either channel.
130   *
131   * @param from the readable channel to read from
132   * @param to the writable channel to write to
133   * @return the number of bytes copied
134   * @throws IOException if an I/O error occurs
135   */
136  @CanIgnoreReturnValue
137  public static long copy(ReadableByteChannel from, WritableByteChannel to) throws IOException {
138    checkNotNull(from);
139    checkNotNull(to);
140    if (from instanceof FileChannel) {
141      FileChannel sourceChannel = (FileChannel) from;
142      long oldPosition = sourceChannel.position();
143      long position = oldPosition;
144      long copied;
145      do {
146        copied = sourceChannel.transferTo(position, ZERO_COPY_CHUNK_SIZE, to);
147        position += copied;
148        sourceChannel.position(position);
149      } while (copied > 0 || position < sourceChannel.size());
150      return position - oldPosition;
151    }
152
153    ByteBuffer buf = ByteBuffer.wrap(createBuffer());
154    long total = 0;
155    while (from.read(buf) != -1) {
156      Java8Compatibility.flip(buf);
157      while (buf.hasRemaining()) {
158        total += to.write(buf);
159      }
160      Java8Compatibility.clear(buf);
161    }
162    return total;
163  }
164
165  /** Max array length on JVM. */
166  private static final int MAX_ARRAY_LEN = Integer.MAX_VALUE - 8;
167
168  /** Large enough to never need to expand, given the geometric progression of buffer sizes. */
169  private static final int TO_BYTE_ARRAY_DEQUE_SIZE = 20;
170
171  /**
172   * Returns a byte array containing the bytes from the buffers already in {@code bufs} (which have
173   * a total combined length of {@code totalLen} bytes) followed by all bytes remaining in the given
174   * input stream.
175   */
176  private static byte[] toByteArrayInternal(InputStream in, Queue<byte[]> bufs, int totalLen)
177      throws IOException {
178    // Roughly size to match what has been read already. Some file systems, such as procfs, return 0
179    // as their length. These files are very small, so it's wasteful to allocate an 8KB buffer.
180    int initialBufferSize = min(BUFFER_SIZE, max(128, Integer.highestOneBit(totalLen) * 2));
181    // Starting with an 8k buffer, double the size of each successive buffer. Smaller buffers
182    // quadruple in size until they reach 8k, to minimize the number of small reads for longer
183    // streams. Buffers are retained in a deque so that there's no copying between buffers while
184    // reading and so all of the bytes in each new allocated buffer are available for reading from
185    // the stream.
186    for (int bufSize = initialBufferSize;
187        totalLen < MAX_ARRAY_LEN;
188        bufSize = IntMath.saturatedMultiply(bufSize, bufSize < 4096 ? 4 : 2)) {
189      byte[] buf = new byte[min(bufSize, MAX_ARRAY_LEN - totalLen)];
190      bufs.add(buf);
191      int off = 0;
192      while (off < buf.length) {
193        // always OK to fill buf; its size plus the rest of bufs is never more than MAX_ARRAY_LEN
194        int r = in.read(buf, off, buf.length - off);
195        if (r == -1) {
196          return combineBuffers(bufs, totalLen);
197        }
198        off += r;
199        totalLen += r;
200      }
201    }
202
203    // read MAX_ARRAY_LEN bytes without seeing end of stream
204    if (in.read() == -1) {
205      // oh, there's the end of the stream
206      return combineBuffers(bufs, MAX_ARRAY_LEN);
207    } else {
208      throw new OutOfMemoryError("input is too large to fit in a byte array");
209    }
210  }
211
212  private static byte[] combineBuffers(Queue<byte[]> bufs, int totalLen) {
213    if (bufs.isEmpty()) {
214      return new byte[0];
215    }
216    byte[] result = bufs.remove();
217    if (result.length == totalLen) {
218      return result;
219    }
220    int remaining = totalLen - result.length;
221    result = Arrays.copyOf(result, totalLen);
222    while (remaining > 0) {
223      byte[] buf = bufs.remove();
224      int bytesToCopy = min(remaining, buf.length);
225      int resultOffset = totalLen - remaining;
226      System.arraycopy(buf, 0, result, resultOffset, bytesToCopy);
227      remaining -= bytesToCopy;
228    }
229    return result;
230  }
231
232  /**
233   * Reads all bytes from an input stream into a byte array. Does not close the stream.
234   *
235   * <p><b>Java 9+ users:</b> use {@code in#readAllBytes()} instead.
236   *
237   * @param in the input stream to read from
238   * @return a byte array containing all the bytes from the stream
239   * @throws IOException if an I/O error occurs
240   */
241  public static byte[] toByteArray(InputStream in) throws IOException {
242    checkNotNull(in);
243    return toByteArrayInternal(in, new ArrayDeque<byte[]>(TO_BYTE_ARRAY_DEQUE_SIZE), 0);
244  }
245
246  /**
247   * Reads all bytes from an input stream into a byte array. The given expected size is used to
248   * create an initial byte array, but if the actual number of bytes read from the stream differs,
249   * the correct result will be returned anyway.
250   */
251  static byte[] toByteArray(InputStream in, long expectedSize) throws IOException {
252    checkArgument(expectedSize >= 0, "expectedSize (%s) must be non-negative", expectedSize);
253    if (expectedSize > MAX_ARRAY_LEN) {
254      throw new OutOfMemoryError(expectedSize + " bytes is too large to fit in a byte array");
255    }
256
257    byte[] bytes = new byte[(int) expectedSize];
258    int remaining = (int) expectedSize;
259
260    while (remaining > 0) {
261      int off = (int) expectedSize - remaining;
262      int read = in.read(bytes, off, remaining);
263      if (read == -1) {
264        // end of stream before reading expectedSize bytes
265        // just return the bytes read so far
266        return Arrays.copyOf(bytes, off);
267      }
268      remaining -= read;
269    }
270
271    // bytes is now full
272    int b = in.read();
273    if (b == -1) {
274      return bytes;
275    }
276
277    // the stream was longer, so read the rest normally
278    Queue<byte[]> bufs = new ArrayDeque<>(TO_BYTE_ARRAY_DEQUE_SIZE + 2);
279    bufs.add(bytes);
280    bufs.add(new byte[] {(byte) b});
281    return toByteArrayInternal(in, bufs, bytes.length + 1);
282  }
283
284  /**
285   * Reads and discards data from the given {@code InputStream} until the end of the stream is
286   * reached. Returns the total number of bytes read. Does not close the stream.
287   *
288   * @since 20.0
289   */
290  @CanIgnoreReturnValue
291  public static long exhaust(InputStream in) throws IOException {
292    long total = 0;
293    long read;
294    byte[] buf = createBuffer();
295    while ((read = in.read(buf)) != -1) {
296      total += read;
297    }
298    return total;
299  }
300
301  /**
302   * Returns a new {@link ByteArrayDataInput} instance to read from the {@code bytes} array from the
303   * beginning.
304   */
305  public static ByteArrayDataInput newDataInput(byte[] bytes) {
306    return newDataInput(new ByteArrayInputStream(bytes));
307  }
308
309  /**
310   * Returns a new {@link ByteArrayDataInput} instance to read from the {@code bytes} array,
311   * starting at the given position.
312   *
313   * @throws IndexOutOfBoundsException if {@code start} is negative or greater than the length of
314   *     the array
315   */
316  public static ByteArrayDataInput newDataInput(byte[] bytes, int start) {
317    checkPositionIndex(start, bytes.length);
318    return newDataInput(new ByteArrayInputStream(bytes, start, bytes.length - start));
319  }
320
321  /**
322   * Returns a new {@link ByteArrayDataInput} instance to read from the given {@code
323   * ByteArrayInputStream}. The given input stream is not reset before being read from by the
324   * returned {@code ByteArrayDataInput}.
325   *
326   * @since 17.0
327   */
328  public static ByteArrayDataInput newDataInput(ByteArrayInputStream byteArrayInputStream) {
329    return new ByteArrayDataInputStream(checkNotNull(byteArrayInputStream));
330  }
331
332  private static class ByteArrayDataInputStream implements ByteArrayDataInput {
333    final DataInput input;
334
335    ByteArrayDataInputStream(ByteArrayInputStream byteArrayInputStream) {
336      this.input = new DataInputStream(byteArrayInputStream);
337    }
338
339    @Override
340    public void readFully(byte b[]) {
341      try {
342        input.readFully(b);
343      } catch (IOException e) {
344        throw new IllegalStateException(e);
345      }
346    }
347
348    @Override
349    public void readFully(byte b[], int off, int len) {
350      try {
351        input.readFully(b, off, len);
352      } catch (IOException e) {
353        throw new IllegalStateException(e);
354      }
355    }
356
357    @Override
358    public int skipBytes(int n) {
359      try {
360        return input.skipBytes(n);
361      } catch (IOException e) {
362        throw new IllegalStateException(e);
363      }
364    }
365
366    @Override
367    public boolean readBoolean() {
368      try {
369        return input.readBoolean();
370      } catch (IOException e) {
371        throw new IllegalStateException(e);
372      }
373    }
374
375    @Override
376    public byte readByte() {
377      try {
378        return input.readByte();
379      } catch (EOFException e) {
380        throw new IllegalStateException(e);
381      } catch (IOException impossible) {
382        throw new AssertionError(impossible);
383      }
384    }
385
386    @Override
387    public int readUnsignedByte() {
388      try {
389        return input.readUnsignedByte();
390      } catch (IOException e) {
391        throw new IllegalStateException(e);
392      }
393    }
394
395    @Override
396    public short readShort() {
397      try {
398        return input.readShort();
399      } catch (IOException e) {
400        throw new IllegalStateException(e);
401      }
402    }
403
404    @Override
405    public int readUnsignedShort() {
406      try {
407        return input.readUnsignedShort();
408      } catch (IOException e) {
409        throw new IllegalStateException(e);
410      }
411    }
412
413    @Override
414    public char readChar() {
415      try {
416        return input.readChar();
417      } catch (IOException e) {
418        throw new IllegalStateException(e);
419      }
420    }
421
422    @Override
423    public int readInt() {
424      try {
425        return input.readInt();
426      } catch (IOException e) {
427        throw new IllegalStateException(e);
428      }
429    }
430
431    @Override
432    public long readLong() {
433      try {
434        return input.readLong();
435      } catch (IOException e) {
436        throw new IllegalStateException(e);
437      }
438    }
439
440    @Override
441    public float readFloat() {
442      try {
443        return input.readFloat();
444      } catch (IOException e) {
445        throw new IllegalStateException(e);
446      }
447    }
448
449    @Override
450    public double readDouble() {
451      try {
452        return input.readDouble();
453      } catch (IOException e) {
454        throw new IllegalStateException(e);
455      }
456    }
457
458    @Override
459    @CheckForNull
460    public String readLine() {
461      try {
462        return input.readLine();
463      } catch (IOException e) {
464        throw new IllegalStateException(e);
465      }
466    }
467
468    @Override
469    public String readUTF() {
470      try {
471        return input.readUTF();
472      } catch (IOException e) {
473        throw new IllegalStateException(e);
474      }
475    }
476  }
477
478  /** Returns a new {@link ByteArrayDataOutput} instance with a default size. */
479  public static ByteArrayDataOutput newDataOutput() {
480    return newDataOutput(new ByteArrayOutputStream());
481  }
482
483  /**
484   * Returns a new {@link ByteArrayDataOutput} instance sized to hold {@code size} bytes before
485   * resizing.
486   *
487   * @throws IllegalArgumentException if {@code size} is negative
488   */
489  public static ByteArrayDataOutput newDataOutput(int size) {
490    // When called at high frequency, boxing size generates too much garbage,
491    // so avoid doing that if we can.
492    if (size < 0) {
493      throw new IllegalArgumentException(String.format("Invalid size: %s", size));
494    }
495    return newDataOutput(new ByteArrayOutputStream(size));
496  }
497
498  /**
499   * Returns a new {@link ByteArrayDataOutput} instance which writes to the given {@code
500   * ByteArrayOutputStream}. The given output stream is not reset before being written to by the
501   * returned {@code ByteArrayDataOutput} and new data will be appended to any existing content.
502   *
503   * <p>Note that if the given output stream was not empty or is modified after the {@code
504   * ByteArrayDataOutput} is created, the contract for {@link ByteArrayDataOutput#toByteArray} will
505   * not be honored (the bytes returned in the byte array may not be exactly what was written via
506   * calls to {@code ByteArrayDataOutput}).
507   *
508   * @since 17.0
509   */
510  public static ByteArrayDataOutput newDataOutput(ByteArrayOutputStream byteArrayOutputStream) {
511    return new ByteArrayDataOutputStream(checkNotNull(byteArrayOutputStream));
512  }
513
514  private static class ByteArrayDataOutputStream implements ByteArrayDataOutput {
515
516    final DataOutput output;
517    final ByteArrayOutputStream byteArrayOutputStream;
518
519    ByteArrayDataOutputStream(ByteArrayOutputStream byteArrayOutputStream) {
520      this.byteArrayOutputStream = byteArrayOutputStream;
521      output = new DataOutputStream(byteArrayOutputStream);
522    }
523
524    @Override
525    public void write(int b) {
526      try {
527        output.write(b);
528      } catch (IOException impossible) {
529        throw new AssertionError(impossible);
530      }
531    }
532
533    @Override
534    public void write(byte[] b) {
535      try {
536        output.write(b);
537      } catch (IOException impossible) {
538        throw new AssertionError(impossible);
539      }
540    }
541
542    @Override
543    public void write(byte[] b, int off, int len) {
544      try {
545        output.write(b, off, len);
546      } catch (IOException impossible) {
547        throw new AssertionError(impossible);
548      }
549    }
550
551    @Override
552    public void writeBoolean(boolean v) {
553      try {
554        output.writeBoolean(v);
555      } catch (IOException impossible) {
556        throw new AssertionError(impossible);
557      }
558    }
559
560    @Override
561    public void writeByte(int v) {
562      try {
563        output.writeByte(v);
564      } catch (IOException impossible) {
565        throw new AssertionError(impossible);
566      }
567    }
568
569    @Override
570    public void writeBytes(String s) {
571      try {
572        output.writeBytes(s);
573      } catch (IOException impossible) {
574        throw new AssertionError(impossible);
575      }
576    }
577
578    @Override
579    public void writeChar(int v) {
580      try {
581        output.writeChar(v);
582      } catch (IOException impossible) {
583        throw new AssertionError(impossible);
584      }
585    }
586
587    @Override
588    public void writeChars(String s) {
589      try {
590        output.writeChars(s);
591      } catch (IOException impossible) {
592        throw new AssertionError(impossible);
593      }
594    }
595
596    @Override
597    public void writeDouble(double v) {
598      try {
599        output.writeDouble(v);
600      } catch (IOException impossible) {
601        throw new AssertionError(impossible);
602      }
603    }
604
605    @Override
606    public void writeFloat(float v) {
607      try {
608        output.writeFloat(v);
609      } catch (IOException impossible) {
610        throw new AssertionError(impossible);
611      }
612    }
613
614    @Override
615    public void writeInt(int v) {
616      try {
617        output.writeInt(v);
618      } catch (IOException impossible) {
619        throw new AssertionError(impossible);
620      }
621    }
622
623    @Override
624    public void writeLong(long v) {
625      try {
626        output.writeLong(v);
627      } catch (IOException impossible) {
628        throw new AssertionError(impossible);
629      }
630    }
631
632    @Override
633    public void writeShort(int v) {
634      try {
635        output.writeShort(v);
636      } catch (IOException impossible) {
637        throw new AssertionError(impossible);
638      }
639    }
640
641    @Override
642    public void writeUTF(String s) {
643      try {
644        output.writeUTF(s);
645      } catch (IOException impossible) {
646        throw new AssertionError(impossible);
647      }
648    }
649
650    @Override
651    public byte[] toByteArray() {
652      return byteArrayOutputStream.toByteArray();
653    }
654  }
655
656  private static final OutputStream NULL_OUTPUT_STREAM =
657      new OutputStream() {
658        /** Discards the specified byte. */
659        @Override
660        public void write(int b) {}
661
662        /** Discards the specified byte array. */
663        @Override
664        public void write(byte[] b) {
665          checkNotNull(b);
666        }
667
668        /** Discards the specified byte array. */
669        @Override
670        public void write(byte[] b, int off, int len) {
671          checkNotNull(b);
672          checkPositionIndexes(off, off + len, b.length);
673        }
674
675        @Override
676        public String toString() {
677          return "ByteStreams.nullOutputStream()";
678        }
679      };
680
681  /**
682   * Returns an {@link OutputStream} that simply discards written bytes.
683   *
684   * @since 14.0 (since 1.0 as com.google.common.io.NullOutputStream)
685   */
686  public static OutputStream nullOutputStream() {
687    return NULL_OUTPUT_STREAM;
688  }
689
690  /**
691   * Wraps a {@link InputStream}, limiting the number of bytes which can be read.
692   *
693   * @param in the input stream to be wrapped
694   * @param limit the maximum number of bytes to be read
695   * @return a length-limited {@link InputStream}
696   * @since 14.0 (since 1.0 as com.google.common.io.LimitInputStream)
697   */
698  public static InputStream limit(InputStream in, long limit) {
699    return new LimitedInputStream(in, limit);
700  }
701
702  private static final class LimitedInputStream extends FilterInputStream {
703
704    private long left;
705    private long mark = -1;
706
707    LimitedInputStream(InputStream in, long limit) {
708      super(in);
709      checkNotNull(in);
710      checkArgument(limit >= 0, "limit must be non-negative");
711      left = limit;
712    }
713
714    @Override
715    public int available() throws IOException {
716      return (int) min(in.available(), left);
717    }
718
719    // it's okay to mark even if mark isn't supported, as reset won't work
720    @Override
721    public synchronized void mark(int readLimit) {
722      in.mark(readLimit);
723      mark = left;
724    }
725
726    @Override
727    public int read() throws IOException {
728      if (left == 0) {
729        return -1;
730      }
731
732      int result = in.read();
733      if (result != -1) {
734        --left;
735      }
736      return result;
737    }
738
739    @Override
740    public int read(byte[] b, int off, int len) throws IOException {
741      if (left == 0) {
742        return -1;
743      }
744
745      len = (int) min(len, left);
746      int result = in.read(b, off, len);
747      if (result != -1) {
748        left -= result;
749      }
750      return result;
751    }
752
753    @Override
754    public synchronized void reset() throws IOException {
755      if (!in.markSupported()) {
756        throw new IOException("Mark not supported");
757      }
758      if (mark == -1) {
759        throw new IOException("Mark not set");
760      }
761
762      in.reset();
763      left = mark;
764    }
765
766    @Override
767    public long skip(long n) throws IOException {
768      n = min(n, left);
769      long skipped = in.skip(n);
770      left -= skipped;
771      return skipped;
772    }
773  }
774
775  /**
776   * Attempts to read enough bytes from the stream to fill the given byte array, with the same
777   * behavior as {@link DataInput#readFully(byte[])}. Does not close the stream.
778   *
779   * @param in the input stream to read from.
780   * @param b the buffer into which the data is read.
781   * @throws EOFException if this stream reaches the end before reading all the bytes.
782   * @throws IOException if an I/O error occurs.
783   */
784  public static void readFully(InputStream in, byte[] b) throws IOException {
785    readFully(in, b, 0, b.length);
786  }
787
788  /**
789   * Attempts to read {@code len} bytes from the stream into the given array starting at {@code
790   * off}, with the same behavior as {@link DataInput#readFully(byte[], int, int)}. Does not close
791   * the stream.
792   *
793   * @param in the input stream to read from.
794   * @param b the buffer into which the data is read.
795   * @param off an int specifying the offset into the data.
796   * @param len an int specifying the number of bytes to read.
797   * @throws EOFException if this stream reaches the end before reading all the bytes.
798   * @throws IOException if an I/O error occurs.
799   */
800  public static void readFully(InputStream in, byte[] b, int off, int len) throws IOException {
801    int read = read(in, b, off, len);
802    if (read != len) {
803      throw new EOFException(
804          "reached end of stream after reading " + read + " bytes; " + len + " bytes expected");
805    }
806  }
807
808  /**
809   * Discards {@code n} bytes of data from the input stream. This method will block until the full
810   * amount has been skipped. Does not close the stream.
811   *
812   * @param in the input stream to read from
813   * @param n the number of bytes to skip
814   * @throws EOFException if this stream reaches the end before skipping all the bytes
815   * @throws IOException if an I/O error occurs, or the stream does not support skipping
816   */
817  public static void skipFully(InputStream in, long n) throws IOException {
818    long skipped = skipUpTo(in, n);
819    if (skipped < n) {
820      throw new EOFException(
821          "reached end of stream after skipping " + skipped + " bytes; " + n + " bytes expected");
822    }
823  }
824
825  /**
826   * Discards up to {@code n} bytes of data from the input stream. This method will block until
827   * either the full amount has been skipped or until the end of the stream is reached, whichever
828   * happens first. Returns the total number of bytes skipped.
829   */
830  static long skipUpTo(InputStream in, long n) throws IOException {
831    long totalSkipped = 0;
832    // A buffer is allocated if skipSafely does not skip any bytes.
833    byte[] buf = null;
834
835    while (totalSkipped < n) {
836      long remaining = n - totalSkipped;
837      long skipped = skipSafely(in, remaining);
838
839      if (skipped == 0) {
840        // Do a buffered read since skipSafely could return 0 repeatedly, for example if
841        // in.available() always returns 0 (the default).
842        int skip = (int) min(remaining, BUFFER_SIZE);
843        if (buf == null) {
844          // Allocate a buffer bounded by the maximum size that can be requested, for
845          // example an array of BUFFER_SIZE is unnecessary when the value of remaining
846          // is smaller.
847          buf = new byte[skip];
848        }
849        if ((skipped = in.read(buf, 0, skip)) == -1) {
850          // Reached EOF
851          break;
852        }
853      }
854
855      totalSkipped += skipped;
856    }
857
858    return totalSkipped;
859  }
860
861  /**
862   * Attempts to skip up to {@code n} bytes from the given input stream, but not more than {@code
863   * in.available()} bytes. This prevents {@code FileInputStream} from skipping more bytes than
864   * actually remain in the file, something that it {@linkplain java.io.FileInputStream#skip(long)
865   * specifies} it can do in its Javadoc despite the fact that it is violating the contract of
866   * {@code InputStream.skip()}.
867   */
868  private static long skipSafely(InputStream in, long n) throws IOException {
869    int available = in.available();
870    return available == 0 ? 0 : in.skip(min(available, n));
871  }
872
873  /**
874   * Process the bytes of the given input stream using the given processor.
875   *
876   * @param input the input stream to process
877   * @param processor the object to which to pass the bytes of the stream
878   * @return the result of the byte processor
879   * @throws IOException if an I/O error occurs
880   * @since 14.0
881   */
882  @CanIgnoreReturnValue // some processors won't return a useful result
883  @ParametricNullness
884  public static <T extends @Nullable Object> T readBytes(
885      InputStream input, ByteProcessor<T> processor) throws IOException {
886    checkNotNull(input);
887    checkNotNull(processor);
888
889    byte[] buf = createBuffer();
890    int read;
891    do {
892      read = input.read(buf);
893    } while (read != -1 && processor.processBytes(buf, 0, read));
894    return processor.getResult();
895  }
896
897  /**
898   * Reads some bytes from an input stream and stores them into the buffer array {@code b}. This
899   * method blocks until {@code len} bytes of input data have been read into the array, or end of
900   * file is detected. The number of bytes read is returned, possibly zero. Does not close the
901   * stream.
902   *
903   * <p>A caller can detect EOF if the number of bytes read is less than {@code len}. All subsequent
904   * calls on the same stream will return zero.
905   *
906   * <p>If {@code b} is null, a {@code NullPointerException} is thrown. If {@code off} is negative,
907   * or {@code len} is negative, or {@code off+len} is greater than the length of the array {@code
908   * b}, then an {@code IndexOutOfBoundsException} is thrown. If {@code len} is zero, then no bytes
909   * are read. Otherwise, the first byte read is stored into element {@code b[off]}, the next one
910   * into {@code b[off+1]}, and so on. The number of bytes read is, at most, equal to {@code len}.
911   *
912   * @param in the input stream to read from
913   * @param b the buffer into which the data is read
914   * @param off an int specifying the offset into the data
915   * @param len an int specifying the number of bytes to read
916   * @return the number of bytes read
917   * @throws IOException if an I/O error occurs
918   * @throws IndexOutOfBoundsException if {@code off} is negative, if {@code len} is negative, or if
919   *     {@code off + len} is greater than {@code b.length}
920   */
921  @CanIgnoreReturnValue
922  // Sometimes you don't care how many bytes you actually read, I guess.
923  // (You know that it's either going to read len bytes or stop at EOF.)
924  public static int read(InputStream in, byte[] b, int off, int len) throws IOException {
925    checkNotNull(in);
926    checkNotNull(b);
927    if (len < 0) {
928      throw new IndexOutOfBoundsException(String.format("len (%s) cannot be negative", len));
929    }
930    checkPositionIndexes(off, off + len, b.length);
931    int total = 0;
932    while (total < len) {
933      int result = in.read(b, off + total, len - total);
934      if (result == -1) {
935        break;
936      }
937      total += result;
938    }
939    return total;
940  }
941}