MemorizingBufferedInputStream extends FilterInputStream { @Override public synchronized int read(final byte[] b, final int off, final int len) throws IOException { if (isClosed) { throw new IOException("Stream is closed " + this); } if (len < 0 || off + len > b.length) { throw new ArrayIndexOutOfBoundsException("Offset " + off + " or len " + len); } int availableToRead = availableToRead(); if (availableToRead <= 0) { fill(); availableToRead = availableToRead(); } if (availableToRead == 0) { if (isEof) { return -1; } else { throw new IllegalStateException("State=" + this); } } int toRead = Math.min(availableToRead, len); int readToEnd = Math.min(toRead, memory.length - startIdx); System.arraycopy(memory, startIdx, b, off, readToEnd); startIdx += readToEnd; int wrapArround = toRead - readToEnd; if (wrapArround > 0) { System.arraycopy(memory, 0, b, off + readToEnd, wrapArround); startIdx = wrapArround; } else if (startIdx >= memory.length) { startIdx = 0; } this.readBytes += toRead; return toRead; } MemorizingBufferedInputStream(final InputStream in);  MemorizingBufferedInputStream(final InputStream in, final int size);  MemorizingBufferedInputStream(final InputStream in, final Charset charset);  MemorizingBufferedInputStream(final InputStream in, final Charset charset, final int size);  MemorizingBufferedInputStream(final InputStream in,
            final int size, final int readSize,
            final SizedRecyclingSupplier<byte[]> bufferProvider,
            @Nullable final Charset charset); @Override @DischargesObligation synchronized void close(); synchronized byte[] getReadBytesFromBuffer(); synchronized byte[] getUnreadBytesFromBuffer(); @Override synchronized int read(final byte[] b, final int off, final int len); @Override synchronized int read(); @Override synchronized int available(); @Override synchronized String toString(); synchronized long getReadBytes(); @Override synchronized long skip(final long n); @Override boolean markSupported(); @Override synchronized void reset(); @Override synchronized void mark(final int readlimit);  }
@Test public void testSimpleStreamBuffering() throws IOException { final byte[] array = Strings.toUtf8(TSTR); ByteArrayInputStream bis = new ByteArrayInputStream(array); MemorizingBufferedInputStream mis = new MemorizingBufferedInputStream(bis); int val; int i = 0; while ((val = mis.read()) > 0) { System.out.print((char) val); Assert.assertEquals(array[i], (byte) val); i++; } Assert.assertEquals(i, array.length); }