• 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");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.google.common.io;
18 
19 import static com.google.common.base.Preconditions.checkArgument;
20 import static com.google.common.base.Preconditions.checkNotNull;
21 import static com.google.common.base.Preconditions.checkPositionIndex;
22 
23 import com.google.common.annotations.Beta;
24 
25 import java.io.ByteArrayInputStream;
26 import java.io.ByteArrayOutputStream;
27 import java.io.DataInput;
28 import java.io.DataInputStream;
29 import java.io.DataOutput;
30 import java.io.DataOutputStream;
31 import java.io.EOFException;
32 import java.io.FilterInputStream;
33 import java.io.IOException;
34 import java.io.InputStream;
35 import java.io.OutputStream;
36 import java.nio.ByteBuffer;
37 import java.nio.channels.ReadableByteChannel;
38 import java.nio.channels.WritableByteChannel;
39 import java.util.Arrays;
40 
41 /**
42  * Provides utility methods for working with byte arrays and I/O streams.
43  *
44  * @author Chris Nokleberg
45  * @author Colin Decker
46  * @since 1.0
47  */
48 @Beta
49 public final class ByteStreams {
50   private static final int BUF_SIZE = 0x1000; // 4K
51 
ByteStreams()52   private ByteStreams() {}
53 
54   /**
55    * Copies all bytes from the input stream to the output stream.
56    * Does not close or flush either stream.
57    *
58    * @param from the input stream to read from
59    * @param to the output stream to write to
60    * @return the number of bytes copied
61    * @throws IOException if an I/O error occurs
62    */
copy(InputStream from, OutputStream to)63   public static long copy(InputStream from, OutputStream to)
64       throws IOException {
65     checkNotNull(from);
66     checkNotNull(to);
67     byte[] buf = new byte[BUF_SIZE];
68     long total = 0;
69     while (true) {
70       int r = from.read(buf);
71       if (r == -1) {
72         break;
73       }
74       to.write(buf, 0, r);
75       total += r;
76     }
77     return total;
78   }
79 
80   /**
81    * Copies all bytes from the readable channel to the writable channel.
82    * Does not close or flush either channel.
83    *
84    * @param from the readable channel to read from
85    * @param to the writable channel to write to
86    * @return the number of bytes copied
87    * @throws IOException if an I/O error occurs
88    */
copy(ReadableByteChannel from, WritableByteChannel to)89   public static long copy(ReadableByteChannel from,
90       WritableByteChannel to) throws IOException {
91     checkNotNull(from);
92     checkNotNull(to);
93     ByteBuffer buf = ByteBuffer.allocate(BUF_SIZE);
94     long total = 0;
95     while (from.read(buf) != -1) {
96       buf.flip();
97       while (buf.hasRemaining()) {
98         total += to.write(buf);
99       }
100       buf.clear();
101     }
102     return total;
103   }
104 
105   /**
106    * Reads all bytes from an input stream into a byte array.
107    * Does not close the stream.
108    *
109    * @param in the input stream to read from
110    * @return a byte array containing all the bytes from the stream
111    * @throws IOException if an I/O error occurs
112    */
toByteArray(InputStream in)113   public static byte[] toByteArray(InputStream in) throws IOException {
114     ByteArrayOutputStream out = new ByteArrayOutputStream();
115     copy(in, out);
116     return out.toByteArray();
117   }
118 
119   /**
120    * Reads all bytes from an input stream into a byte array. The given
121    * expected size is used to create an initial byte array, but if the actual
122    * number of bytes read from the stream differs, the correct result will be
123    * returned anyway.
124    */
toByteArray( InputStream in, int expectedSize)125   static byte[] toByteArray(
126       InputStream in, int expectedSize) throws IOException {
127     byte[] bytes = new byte[expectedSize];
128     int remaining = expectedSize;
129 
130     while (remaining > 0) {
131       int off = expectedSize - remaining;
132       int read = in.read(bytes, off, remaining);
133       if (read == -1) {
134         // end of stream before reading expectedSize bytes
135         // just return the bytes read so far
136         return Arrays.copyOf(bytes, off);
137       }
138       remaining -= read;
139     }
140 
141     // bytes is now full
142     int b = in.read();
143     if (b == -1) {
144       return bytes;
145     }
146 
147     // the stream was longer, so read the rest normally
148     FastByteArrayOutputStream out = new FastByteArrayOutputStream();
149     out.write(b); // write the byte we read when testing for end of stream
150     copy(in, out);
151 
152     byte[] result = new byte[bytes.length + out.size()];
153     System.arraycopy(bytes, 0, result, 0, bytes.length);
154     out.writeTo(result, bytes.length);
155     return result;
156   }
157 
158   /**
159    * BAOS that provides limited access to its internal byte array.
160    */
161   private static final class FastByteArrayOutputStream
162       extends ByteArrayOutputStream {
163     /**
164      * Writes the contents of the internal buffer to the given array starting
165      * at the given offset. Assumes the array has space to hold count bytes.
166      */
writeTo(byte[] b, int off)167     void writeTo(byte[] b, int off) {
168       System.arraycopy(buf, 0, b, off, count);
169     }
170   }
171 
172   /**
173    * Returns a new {@link ByteArrayDataInput} instance to read from the {@code
174    * bytes} array from the beginning.
175    */
newDataInput(byte[] bytes)176   public static ByteArrayDataInput newDataInput(byte[] bytes) {
177     return newDataInput(new ByteArrayInputStream(bytes));
178   }
179 
180   /**
181    * Returns a new {@link ByteArrayDataInput} instance to read from the {@code
182    * bytes} array, starting at the given position.
183    *
184    * @throws IndexOutOfBoundsException if {@code start} is negative or greater
185    *     than the length of the array
186    */
newDataInput(byte[] bytes, int start)187   public static ByteArrayDataInput newDataInput(byte[] bytes, int start) {
188     checkPositionIndex(start, bytes.length);
189     return newDataInput(
190         new ByteArrayInputStream(bytes, start, bytes.length - start));
191   }
192 
193   /**
194    * Returns a new {@link ByteArrayDataInput} instance to read from the given
195    * {@code ByteArrayInputStream}. The given input stream is not reset before
196    * being read from by the returned {@code ByteArrayDataInput}.
197    *
198    * @since 17.0
199    */
newDataInput( ByteArrayInputStream byteArrayInputStream)200   public static ByteArrayDataInput newDataInput(
201       ByteArrayInputStream byteArrayInputStream) {
202     return new ByteArrayDataInputStream(checkNotNull(byteArrayInputStream));
203   }
204 
205   private static class ByteArrayDataInputStream implements ByteArrayDataInput {
206     final DataInput input;
207 
ByteArrayDataInputStream(ByteArrayInputStream byteArrayInputStream)208     ByteArrayDataInputStream(ByteArrayInputStream byteArrayInputStream) {
209       this.input = new DataInputStream(byteArrayInputStream);
210     }
211 
readFully(byte b[])212     @Override public void readFully(byte b[]) {
213       try {
214         input.readFully(b);
215       } catch (IOException e) {
216         throw new IllegalStateException(e);
217       }
218     }
219 
readFully(byte b[], int off, int len)220     @Override public void readFully(byte b[], int off, int len) {
221       try {
222         input.readFully(b, off, len);
223       } catch (IOException e) {
224         throw new IllegalStateException(e);
225       }
226     }
227 
skipBytes(int n)228     @Override public int skipBytes(int n) {
229       try {
230         return input.skipBytes(n);
231       } catch (IOException e) {
232         throw new IllegalStateException(e);
233       }
234     }
235 
readBoolean()236     @Override public boolean readBoolean() {
237       try {
238         return input.readBoolean();
239       } catch (IOException e) {
240         throw new IllegalStateException(e);
241       }
242     }
243 
readByte()244     @Override public byte readByte() {
245       try {
246         return input.readByte();
247       } catch (EOFException e) {
248         throw new IllegalStateException(e);
249       } catch (IOException impossible) {
250         throw new AssertionError(impossible);
251       }
252     }
253 
readUnsignedByte()254     @Override public int readUnsignedByte() {
255       try {
256         return input.readUnsignedByte();
257       } catch (IOException e) {
258         throw new IllegalStateException(e);
259       }
260     }
261 
readShort()262     @Override public short readShort() {
263       try {
264         return input.readShort();
265       } catch (IOException e) {
266         throw new IllegalStateException(e);
267       }
268     }
269 
readUnsignedShort()270     @Override public int readUnsignedShort() {
271       try {
272         return input.readUnsignedShort();
273       } catch (IOException e) {
274         throw new IllegalStateException(e);
275       }
276     }
277 
readChar()278     @Override public char readChar() {
279       try {
280         return input.readChar();
281       } catch (IOException e) {
282         throw new IllegalStateException(e);
283       }
284     }
285 
readInt()286     @Override public int readInt() {
287       try {
288         return input.readInt();
289       } catch (IOException e) {
290         throw new IllegalStateException(e);
291       }
292     }
293 
readLong()294     @Override public long readLong() {
295       try {
296         return input.readLong();
297       } catch (IOException e) {
298         throw new IllegalStateException(e);
299       }
300     }
301 
readFloat()302     @Override public float readFloat() {
303       try {
304         return input.readFloat();
305       } catch (IOException e) {
306         throw new IllegalStateException(e);
307       }
308     }
309 
readDouble()310     @Override public double readDouble() {
311       try {
312         return input.readDouble();
313       } catch (IOException e) {
314         throw new IllegalStateException(e);
315       }
316     }
317 
readLine()318     @Override public String readLine() {
319       try {
320         return input.readLine();
321       } catch (IOException e) {
322         throw new IllegalStateException(e);
323       }
324     }
325 
readUTF()326     @Override public String readUTF() {
327       try {
328         return input.readUTF();
329       } catch (IOException e) {
330         throw new IllegalStateException(e);
331       }
332     }
333   }
334 
335   /**
336    * Returns a new {@link ByteArrayDataOutput} instance with a default size.
337    */
newDataOutput()338   public static ByteArrayDataOutput newDataOutput() {
339     return newDataOutput(new ByteArrayOutputStream());
340   }
341 
342   /**
343    * Returns a new {@link ByteArrayDataOutput} instance sized to hold
344    * {@code size} bytes before resizing.
345    *
346    * @throws IllegalArgumentException if {@code size} is negative
347    */
newDataOutput(int size)348   public static ByteArrayDataOutput newDataOutput(int size) {
349     checkArgument(size >= 0, "Invalid size: %s", size);
350     return newDataOutput(new ByteArrayOutputStream(size));
351   }
352 
353   /**
354    * Returns a new {@link ByteArrayDataOutput} instance which writes to the
355    * given {@code ByteArrayOutputStream}. The given output stream is not reset
356    * before being written to by the returned {@code ByteArrayDataOutput} and
357    * new data will be appended to any existing content.
358    *
359    * <p>Note that if the given output stream was not empty or is modified after
360    * the {@code ByteArrayDataOutput} is created, the contract for
361    * {@link ByteArrayDataOutput#toByteArray} will not be honored (the bytes
362    * returned in the byte array may not be exactly what was written via calls to
363    * {@code ByteArrayDataOutput}).
364    *
365    * @since 17.0
366    */
newDataOutput( ByteArrayOutputStream byteArrayOutputSteam)367   public static ByteArrayDataOutput newDataOutput(
368       ByteArrayOutputStream byteArrayOutputSteam) {
369     return new ByteArrayDataOutputStream(checkNotNull(byteArrayOutputSteam));
370   }
371 
372   @SuppressWarnings("deprecation") // for writeBytes
373   private static class ByteArrayDataOutputStream
374       implements ByteArrayDataOutput {
375 
376     final DataOutput output;
377     final ByteArrayOutputStream byteArrayOutputSteam;
378 
ByteArrayDataOutputStream(ByteArrayOutputStream byteArrayOutputSteam)379     ByteArrayDataOutputStream(ByteArrayOutputStream byteArrayOutputSteam) {
380       this.byteArrayOutputSteam = byteArrayOutputSteam;
381       output = new DataOutputStream(byteArrayOutputSteam);
382     }
383 
write(int b)384     @Override public void write(int b) {
385       try {
386         output.write(b);
387       } catch (IOException impossible) {
388         throw new AssertionError(impossible);
389       }
390     }
391 
write(byte[] b)392     @Override public void write(byte[] b) {
393       try {
394         output.write(b);
395       } catch (IOException impossible) {
396         throw new AssertionError(impossible);
397       }
398     }
399 
write(byte[] b, int off, int len)400     @Override public void write(byte[] b, int off, int len) {
401       try {
402         output.write(b, off, len);
403       } catch (IOException impossible) {
404         throw new AssertionError(impossible);
405       }
406     }
407 
writeBoolean(boolean v)408     @Override public void writeBoolean(boolean v) {
409       try {
410         output.writeBoolean(v);
411       } catch (IOException impossible) {
412         throw new AssertionError(impossible);
413       }
414     }
415 
writeByte(int v)416     @Override public void writeByte(int v) {
417       try {
418         output.writeByte(v);
419       } catch (IOException impossible) {
420         throw new AssertionError(impossible);
421       }
422     }
423 
writeBytes(String s)424     @Override public void writeBytes(String s) {
425       try {
426         output.writeBytes(s);
427       } catch (IOException impossible) {
428         throw new AssertionError(impossible);
429       }
430     }
431 
writeChar(int v)432     @Override public void writeChar(int v) {
433       try {
434         output.writeChar(v);
435       } catch (IOException impossible) {
436         throw new AssertionError(impossible);
437       }
438     }
439 
writeChars(String s)440     @Override public void writeChars(String s) {
441       try {
442         output.writeChars(s);
443       } catch (IOException impossible) {
444         throw new AssertionError(impossible);
445       }
446     }
447 
writeDouble(double v)448     @Override public void writeDouble(double v) {
449       try {
450         output.writeDouble(v);
451       } catch (IOException impossible) {
452         throw new AssertionError(impossible);
453       }
454     }
455 
writeFloat(float v)456     @Override public void writeFloat(float v) {
457       try {
458         output.writeFloat(v);
459       } catch (IOException impossible) {
460         throw new AssertionError(impossible);
461       }
462     }
463 
writeInt(int v)464     @Override public void writeInt(int v) {
465       try {
466         output.writeInt(v);
467       } catch (IOException impossible) {
468         throw new AssertionError(impossible);
469       }
470     }
471 
writeLong(long v)472     @Override public void writeLong(long v) {
473       try {
474         output.writeLong(v);
475       } catch (IOException impossible) {
476         throw new AssertionError(impossible);
477       }
478     }
479 
writeShort(int v)480     @Override public void writeShort(int v) {
481       try {
482         output.writeShort(v);
483       } catch (IOException impossible) {
484         throw new AssertionError(impossible);
485       }
486     }
487 
writeUTF(String s)488     @Override public void writeUTF(String s) {
489       try {
490         output.writeUTF(s);
491       } catch (IOException impossible) {
492         throw new AssertionError(impossible);
493       }
494     }
495 
toByteArray()496     @Override public byte[] toByteArray() {
497       return byteArrayOutputSteam.toByteArray();
498     }
499   }
500 
501   private static final OutputStream NULL_OUTPUT_STREAM =
502       new OutputStream() {
503         /** Discards the specified byte. */
504         @Override public void write(int b) {
505         }
506         /** Discards the specified byte array. */
507         @Override public void write(byte[] b) {
508           checkNotNull(b);
509         }
510         /** Discards the specified byte array. */
511         @Override public void write(byte[] b, int off, int len) {
512           checkNotNull(b);
513         }
514 
515         @Override
516         public String toString() {
517           return "ByteStreams.nullOutputStream()";
518         }
519       };
520 
521   /**
522    * Returns an {@link OutputStream} that simply discards written bytes.
523    *
524    * @since 14.0 (since 1.0 as com.google.common.io.NullOutputStream)
525    */
nullOutputStream()526   public static OutputStream nullOutputStream() {
527     return NULL_OUTPUT_STREAM;
528   }
529 
530   /**
531    * Wraps a {@link InputStream}, limiting the number of bytes which can be
532    * read.
533    *
534    * @param in the input stream to be wrapped
535    * @param limit the maximum number of bytes to be read
536    * @return a length-limited {@link InputStream}
537    * @since 14.0 (since 1.0 as com.google.common.io.LimitInputStream)
538    */
limit(InputStream in, long limit)539   public static InputStream limit(InputStream in, long limit) {
540     return new LimitedInputStream(in, limit);
541   }
542 
543   private static final class LimitedInputStream extends FilterInputStream {
544 
545     private long left;
546     private long mark = -1;
547 
LimitedInputStream(InputStream in, long limit)548     LimitedInputStream(InputStream in, long limit) {
549       super(in);
550       checkNotNull(in);
551       checkArgument(limit >= 0, "limit must be non-negative");
552       left = limit;
553     }
554 
available()555     @Override public int available() throws IOException {
556       return (int) Math.min(in.available(), left);
557     }
558 
559     // it's okay to mark even if mark isn't supported, as reset won't work
mark(int readLimit)560     @Override public synchronized void mark(int readLimit) {
561       in.mark(readLimit);
562       mark = left;
563     }
564 
read()565     @Override public int read() throws IOException {
566       if (left == 0) {
567         return -1;
568       }
569 
570       int result = in.read();
571       if (result != -1) {
572         --left;
573       }
574       return result;
575     }
576 
read(byte[] b, int off, int len)577     @Override public int read(byte[] b, int off, int len) throws IOException {
578       if (left == 0) {
579         return -1;
580       }
581 
582       len = (int) Math.min(len, left);
583       int result = in.read(b, off, len);
584       if (result != -1) {
585         left -= result;
586       }
587       return result;
588     }
589 
reset()590     @Override public synchronized void reset() throws IOException {
591       if (!in.markSupported()) {
592         throw new IOException("Mark not supported");
593       }
594       if (mark == -1) {
595         throw new IOException("Mark not set");
596       }
597 
598       in.reset();
599       left = mark;
600     }
601 
skip(long n)602     @Override public long skip(long n) throws IOException {
603       n = Math.min(n, left);
604       long skipped = in.skip(n);
605       left -= skipped;
606       return skipped;
607     }
608   }
609 
610   /**
611    * Attempts to read enough bytes from the stream to fill the given byte array,
612    * with the same behavior as {@link DataInput#readFully(byte[])}.
613    * Does not close the stream.
614    *
615    * @param in the input stream to read from.
616    * @param b the buffer into which the data is read.
617    * @throws EOFException if this stream reaches the end before reading all
618    *     the bytes.
619    * @throws IOException if an I/O error occurs.
620    */
readFully(InputStream in, byte[] b)621   public static void readFully(InputStream in, byte[] b) throws IOException {
622     readFully(in, b, 0, b.length);
623   }
624 
625   /**
626    * Attempts to read {@code len} bytes from the stream into the given array
627    * starting at {@code off}, with the same behavior as
628    * {@link DataInput#readFully(byte[], int, int)}. Does not close the
629    * stream.
630    *
631    * @param in the input stream to read from.
632    * @param b the buffer into which the data is read.
633    * @param off an int specifying the offset into the data.
634    * @param len an int specifying the number of bytes to read.
635    * @throws EOFException if this stream reaches the end before reading all
636    *     the bytes.
637    * @throws IOException if an I/O error occurs.
638    */
readFully( InputStream in, byte[] b, int off, int len)639   public static void readFully(
640       InputStream in, byte[] b, int off, int len) throws IOException {
641     int read = read(in, b, off, len);
642     if (read != len) {
643       throw new EOFException("reached end of stream after reading "
644           + read + " bytes; " + len + " bytes expected");
645     }
646   }
647 
648   /**
649    * Discards {@code n} bytes of data from the input stream. This method
650    * will block until the full amount has been skipped. Does not close the
651    * stream.
652    *
653    * @param in the input stream to read from
654    * @param n the number of bytes to skip
655    * @throws EOFException if this stream reaches the end before skipping all
656    *     the bytes
657    * @throws IOException if an I/O error occurs, or the stream does not
658    *     support skipping
659    */
skipFully(InputStream in, long n)660   public static void skipFully(InputStream in, long n) throws IOException {
661     long toSkip = n;
662     while (n > 0) {
663       long amt = in.skip(n);
664       if (amt == 0) {
665         // Force a blocking read to avoid infinite loop
666         if (in.read() == -1) {
667           long skipped = toSkip - n;
668           throw new EOFException("reached end of stream after skipping "
669               + skipped + " bytes; " + toSkip + " bytes expected");
670         }
671         n--;
672       } else {
673         n -= amt;
674       }
675     }
676   }
677 
678   /**
679    * Process the bytes of the given input stream using the given processor.
680    *
681    * @param input the input stream to process
682    * @param processor the object to which to pass the bytes of the stream
683    * @return the result of the byte processor
684    * @throws IOException if an I/O error occurs
685    * @since 14.0
686    */
readBytes( InputStream input, ByteProcessor<T> processor)687   public static <T> T readBytes(
688       InputStream input, ByteProcessor<T> processor) throws IOException {
689     checkNotNull(input);
690     checkNotNull(processor);
691 
692     byte[] buf = new byte[BUF_SIZE];
693     int read;
694     do {
695       read = input.read(buf);
696     } while (read != -1 && processor.processBytes(buf, 0, read));
697     return processor.getResult();
698   }
699 
700   /**
701    * Reads some bytes from an input stream and stores them into the buffer array
702    * {@code b}. This method blocks until {@code len} bytes of input data have
703    * been read into the array, or end of file is detected. The number of bytes
704    * read is returned, possibly zero. Does not close the stream.
705    *
706    * <p>A caller can detect EOF if the number of bytes read is less than
707    * {@code len}. All subsequent calls on the same stream will return zero.
708    *
709    * <p>If {@code b} is null, a {@code NullPointerException} is thrown. If
710    * {@code off} is negative, or {@code len} is negative, or {@code off+len} is
711    * greater than the length of the array {@code b}, then an
712    * {@code IndexOutOfBoundsException} is thrown. If {@code len} is zero, then
713    * no bytes are read. Otherwise, the first byte read is stored into element
714    * {@code b[off]}, the next one into {@code b[off+1]}, and so on. The number
715    * of bytes read is, at most, equal to {@code len}.
716    *
717    * @param in the input stream to read from
718    * @param b the buffer into which the data is read
719    * @param off an int specifying the offset into the data
720    * @param len an int specifying the number of bytes to read
721    * @return the number of bytes read
722    * @throws IOException if an I/O error occurs
723    */
read(InputStream in, byte[] b, int off, int len)724   public static int read(InputStream in, byte[] b, int off, int len)
725       throws IOException {
726     checkNotNull(in);
727     checkNotNull(b);
728     if (len < 0) {
729       throw new IndexOutOfBoundsException("len is negative");
730     }
731     int total = 0;
732     while (total < len) {
733       int result = in.read(b, off + total, len - total);
734       if (result == -1) {
735         break;
736       }
737       total += result;
738     }
739     return total;
740   }
741 }
742