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 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 208 ByteArrayDataInputStream(ByteArrayInputStream byteArrayInputStream) { 209 this.input = new DataInputStream(byteArrayInputStream); 210 } 211 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 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 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 236 @Override public boolean readBoolean() { 237 try { 238 return input.readBoolean(); 239 } catch (IOException e) { 240 throw new IllegalStateException(e); 241 } 242 } 243 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 254 @Override public int readUnsignedByte() { 255 try { 256 return input.readUnsignedByte(); 257 } catch (IOException e) { 258 throw new IllegalStateException(e); 259 } 260 } 261 262 @Override public short readShort() { 263 try { 264 return input.readShort(); 265 } catch (IOException e) { 266 throw new IllegalStateException(e); 267 } 268 } 269 270 @Override public int readUnsignedShort() { 271 try { 272 return input.readUnsignedShort(); 273 } catch (IOException e) { 274 throw new IllegalStateException(e); 275 } 276 } 277 278 @Override public char readChar() { 279 try { 280 return input.readChar(); 281 } catch (IOException e) { 282 throw new IllegalStateException(e); 283 } 284 } 285 286 @Override public int readInt() { 287 try { 288 return input.readInt(); 289 } catch (IOException e) { 290 throw new IllegalStateException(e); 291 } 292 } 293 294 @Override public long readLong() { 295 try { 296 return input.readLong(); 297 } catch (IOException e) { 298 throw new IllegalStateException(e); 299 } 300 } 301 302 @Override public float readFloat() { 303 try { 304 return input.readFloat(); 305 } catch (IOException e) { 306 throw new IllegalStateException(e); 307 } 308 } 309 310 @Override public double readDouble() { 311 try { 312 return input.readDouble(); 313 } catch (IOException e) { 314 throw new IllegalStateException(e); 315 } 316 } 317 318 @Override public String readLine() { 319 try { 320 return input.readLine(); 321 } catch (IOException e) { 322 throw new IllegalStateException(e); 323 } 324 } 325 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 */ 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 */ 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 */ 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 379 ByteArrayDataOutputStream(ByteArrayOutputStream byteArrayOutputSteam) { 380 this.byteArrayOutputSteam = byteArrayOutputSteam; 381 output = new DataOutputStream(byteArrayOutputSteam); 382 } 383 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 */ 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 */ 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 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 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 560 @Override public synchronized void mark(int readLimit) { 561 in.mark(readLimit); 562 mark = left; 563 } 564 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 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 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 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 */ 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 */ 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 */ 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 */ 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 */ 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