o7planning

Java PushbackInputStream Tutorial with Examples

  1. PushbackInputStream
  2. Examples

1. PushbackInputStream

Sometimes when working with a binary input stream, you need to read a few bytes in advance to see what's going to happen, before you can define current byte interpretation, then you can push them back. PushbackInputStream class allows you to do that.
PushbackInputStream manages an InputStream object, which reads data from the origin (such as file). At the same time, PushbackInputStream also manages a byte array - buffer.
At the beginning, there is no byte assigned to buffer array. PushbackInputStream.read method returns bytes from InputStream.read.
If you call PushbackInputStream.unread method to push bytes back, they are stored in buffer array.
The next time you call PushbackInputStream.read method, it returns bytes stored in buffer array. InputStream.read method will only be called if there is no byte in buffer array.
PushbackReader​ constructors
public PushbackReader​(Reader in, int size)

public PushbackReader​(Reader in)
  • PushbackInputStream(InputStream,int) constructor creates a PushbackInputStream object with buffer array that has specified size.
  • PushbackInputStream(InputStream) constructor creates a PushbackInputStream object with buffer array that has default size (size =1).

2. Examples

Suppose you store all the data of 3 images into a single file. They are separated by "@@@". How to read this file and write to 3 image files corresponding to the data?

..bytes..of..image1..@@@..bytes..of..image2..@@@..bytes..of..image3..

Use PushbackInputStream to read content of the above data file. When you encounter byte 64 (@), you need to read the next 2 bytes to decide what to do with the current byte.
PushbackInputStreamEx1.java
package org.o7planning.pushbackinputstream.ex;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PushbackInputStream;
import java.net.URL;

public class PushbackInputStreamEx1 {

    private static final String OUT_FOLDER = "/Volumes/Data/test/icons";
    
    private static final String url = "https://s3.o7planning.com/txt/google-emoticons-data.txt";

    public static void main(String[] args) throws IOException {
        InputStream is = new URL(url).openStream();

        PushbackInputStream pis = new PushbackInputStream(is, 2);
        
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        int fileIdx = 0;

        int code;
        while ((code = pis.read()) != -1) {
            if (code == (int)'@') {
                int next1 = pis.read();
                int next2 = pis.read();

                if (next1 == '@' && next2 == '@') {
                    byte[] imageData = baos.toByteArray();
                    fileIdx++;
                    writeToFile(imageData,fileIdx); // Write Image file.

                    baos = new ByteArrayOutputStream();
                } else {
                    baos.write(code);
                    pis.unread(next2);
                    pis.unread(next1);
                }
            } else {
                baos.write(code);
            }
        }
        byte[] imageData = baos.toByteArray();
        fileIdx++;
        writeToFile(imageData,fileIdx);  // Write Image file.

        pis.close();
    }
    
    private static void writeToFile(byte[] data, int fileIdx) throws IOException {
        File file = new File(OUT_FOLDER +"/" + fileIdx + ".png");
        file.getParentFile().mkdirs();
        System.out.println("Write file: " + file.getAbsolutePath());
        
        FileOutputStream fos = new FileOutputStream(file);
        fos.write(data);
        fos.close();
    }
}
Output:
Write file: /Volumes/Data/test/icons/1.png
Write file: /Volumes/Data/test/icons/2.png
Write file: /Volumes/Data/test/icons/3.png
Using a regular InputStream to read each byte will take a lot of time. You should use BufferedInputStream to improve performance of the above example:
PushbackInputStreamEx1b.java
package org.o7planning.pushbackinputstream.ex;

import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PushbackInputStream;
import java.net.URL;

public class PushbackInputStreamEx1b {

    private static final String OUT_FOLDER = "/Volumes/Data/test/icons";
    
    private static final String url = "https://s3.o7planning.com/txt/google-emoticons-data.txt";

    public static void main(String[] args) throws IOException {
        InputStream is = new URL(url).openStream();
        // Create BufferedInputStream object.
        BufferedInputStream bis = new BufferedInputStream(is);

        PushbackInputStream pis = new PushbackInputStream(bis, 2);
        
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        int fileIdx = 0;

        int code;
        while ((code = pis.read()) != -1) {
            if (code == (int)'@') {
                int next1 = pis.read();
                int next2 = pis.read();

                if (next1 == '@' && next2 == '@') {
                    byte[] imageData = baos.toByteArray();
                    fileIdx++;
                    writeToFile(imageData,fileIdx); // Write Image file.

                    baos = new ByteArrayOutputStream();
                } else {
                    baos.write(code);
                    pis.unread(next2);
                    pis.unread(next1);
                }
            } else {
                baos.write(code);
            }
        }
        byte[] imageData = baos.toByteArray();
        fileIdx++;
        writeToFile(imageData,fileIdx);  // Write Image file.

        pis.close();
    }
    
    private static void writeToFile(byte[] data, int fileIdx) throws IOException {
        File file = new File(OUT_FOLDER +"/" + fileIdx + ".png");
        file.getParentFile().mkdirs();
        System.out.println("Write file: " + file.getAbsolutePath());
        
        FileOutputStream fos = new FileOutputStream(file);
        fos.write(data);
        fos.close();
    }
}

Java IO Tutorials

Show More