/** * Creates a new BoundedInputStream wrapping the same InputStream as this one, starting at the current position, with * the given bound. * * NOTE: both this instance and the result of this method should not be both used at the same time to read from the * InputStream. When this method returns, this instance's remaining count will be reduced by the given bound (that's * since upon closing, the BoundedInputStream will auto-advance to its bound position). * * @param bound The bound of the sub-stream. * @return A new instance of a BoundedInputStream. */ public BoundedInputStream subStream(int bound) { Preconditions.checkArgument(bound >= 0 && bound <= this.remaining, "bound must be a non-negative integer and less than or equal to the remaining length."); this.remaining -= bound; return new BoundedInputStream(this.in, bound); }
/** * Creates a new instance of the RevisionDataInputStream class. Upon a successful call to this method, 4 bytes * will have been read from the InputStream representing the expected length of the serialization. * * @param inputStream The InputStream to wrap. * @throws IOException If an IO Exception occurred. */ static RevisionDataInputStream wrap(InputStream inputStream) throws IOException { int bound = BitConverter.readInt(inputStream); return new RevisionDataInputStream(new BoundedInputStream(inputStream, bound)); }
/** * Interprets the given InputStream as a DataFrame and returns a DataFrameEntryIterator for the entries serialized * in it. * * @param source The InputStream to read from. * @param length The size of the inputStream. * @param address The DataFrame's address. * @return A new DataFrameEntryIterator. * @throws IOException If unable to parse the DataFrame's header from the InputStream. */ public static DataFrameEntryIterator read(InputStream source, int length, LogAddress address) throws IOException { // Check to see that we have enough bytes in the InputStream. ReadFrameHeader header = new ReadFrameHeader(source); if (length < ReadFrameHeader.SERIALIZATION_LENGTH + header.getContentLength()) { throw new SerializationException(String.format("Given buffer has insufficient number of bytes for this DataFrame. Expected %d, actual %d.", ReadFrameHeader.SERIALIZATION_LENGTH + header.getContentLength(), length)); } BoundedInputStream contents = new BoundedInputStream(source, header.getContentLength()); return new DataFrameEntryIterator(contents, address, ReadFrameHeader.SERIALIZATION_LENGTH); }
/** * Tests the ability to skip remaining bytes upon closing. */ @Test public void testSkipRemainingOnClose() throws Exception { for (int size = 0; size < MAX_SIZE; size++) { int bound = size / 2; val data = construct(size); @Cleanup val input = new ByteArrayInputStream(data); @Cleanup val bis = new BoundedInputStream(input, bound); Assert.assertEquals("Unexpected value for getBound().", bound, bis.getBound()); if (size % 2 == 1) { // Only read some data for every other iteration. int bytesRead = bis.read(new byte[bound / 2]); Assert.assertEquals("Unexpected number of bytes read.", bound / 2, bytesRead); } bis.close(); Assert.assertEquals("Unexpected number of bytes remaining to be read after skipRemaining().", data.length - bis.getBound(), input.available()); } }
val input = new ByteArrayInputStream(data); @Cleanup val bis = new BoundedInputStream(input, bound);
val input = new ByteArrayInputStream(data); @Cleanup val bis = new BoundedInputStream(input, bound); int expectedAvailable = bis.getBound();