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