Search code examples
javastreamresetpush-back

PushbackInputStream and mark/reset


I use PushbackInputStream to look ahead the next byte in a stream (bufferedIn which is a BufferedInputStream) because I want to mark() before some value, and later to rewind prior to it using reset().

// Wrap input stream into a push back stream
PushbackInputStream pbBufferedIn = new PushbackInputStream(bufferedIn, 20);
boolean markDone = false; // Flag for mark
boolean resetDone = false; // Flag for reset

// Read each byte in the stream (some twice)
for (int i = pbBufferedIn.read(); i != -1; i = pbBufferedIn.read()) {
    // Convert to byte
    byte b = (byte) i;
    // Check for marking before value -1
    if (!markDone) {
        if (b == -1) {
            // Push character back
            pbBufferedIn.unread(i);
            // Mark for later rewind
            pbBufferedIn.mark(20);
            markDone = true;
            System.out.print("[mark] ");                    
            // Re-read
            pbBufferedIn.read();
        }
    }

    // Print the current byte
    System.out.print(b + " ");

    // Check for rewind after value 1
    if (markDone && !resetDone && b == 1) {
        pbBufferedIn.reset(); // <------ mark/reset not supported!
        resetDone = true;
        System.out.print("[reset] ");
    }
}

Ironically PushbackInputStream doesn't support mark/reset... on the other hand BufferedInputStream that supports mark/reset don't have a push-back mechanism... How can I do?


Solution

  • BufferedInputStream ( stream replay ):

    • you mark now (start creating a buffer) so that you can replay later (at some buffer position).
    • Also you cannot replace the buffered content with something else.

    PushbackInputStream ( stream corrected-replay ):

    • there is always a buffer available to which you can reset (at some buffer position)
    • You can provide the replay contents to that buffer.

    Below I provide the corresponding examples with length-1-buffers for simplicity:

    PushbackInputStream pbis = 
    new PushbackInputStream(new ByteArrayInputStream(new byte[]{'a','b','c'}));
    System.out.println((char)pbis.read());
    System.out.println((char)pbis.read());
    pbis.unread('x'); //pushback after read
    System.out.println((char)pbis.read());        
    System.out.println((char)pbis.read());        
    
    BufferedInputStream bis = 
    new BufferedInputStream(new ByteArrayInputStream(new byte[]{'a','b','c'}));
    System.out.println((char)bis.read());
    bis.mark(1);//mark before read
    System.out.println((char)bis.read());
    bis.reset();//reset after read
    System.out.println((char)bis.read());        
    System.out.println((char)bis.read());
    
    

    Result:

    a
    b
    x   //correction
    c
    
    a
    b
    b   //replay
    c