openplanning

Hướng dẫn và ví dụ Java PushbackInputStream

Xem thêm các chuyên mục:

Hãy theo dõi chúng tôi trên Fanpage để nhận được thông báo mỗi khi có bài viết mới. Facebook

1- PushbackInputStream

Đôi khi làm việc với một luồng đầu vào nhị phân (binary input stream) bạn cần đọc trước một vài bytes để xem điều gì sắp xảy ra, trước khi bạn có thể xác định cách diễn giải byte hiện tại, sau đó bạn có thể đẩy chúng trở lại. Lớp PushbackInputStream cho phép bạn làm điều đó.
PushbackInputStream quản lý một đối tượng InputStream, đối tượng này sẽ đọc dữ liệu từ nguồn gốc (chẳng hạn file), đồng thời PushbackInputStream cũng quản lý một mảng byte - buffer.
Tại thời điểm ban đầu, không có một byte nào được gán vào mảng buffer. Phương thức PushbackInputStream.read sẽ trả về các bytes từ InputStream.read.
Nếu bạn gọi phương thức PushbackInputStream.unread để đẩy các bytes trở lại, chúng sẽ được lưu trữ trên mảng buffer.
Trong lần tiếp theo, nếu bạn gọi phương thức PushbackInputStream.read, nó sẽ trả về các bytes đã được lưu trữ trên mảng buffer. Phương thức InputStream.read sẽ chỉ được gọi nếu không còn byte nào trên mảng buffer.
PushbackReader​ constructors

public PushbackReader​(Reader in, int size)

public PushbackReader​(Reader in)
  • Constructor PushbackInputStream(InputStream,int) tạo ra một đối tượng PushbackInputStream với mảng buffer có kích thước được chỉ định.
  • Constructor PushbackInputStream(InputStream) tạo ra một đối tượng PushbackInputStream với mảng buffer có kích thước mặc định (size = 1).

2- Examples

Giả sử bạn lưu trữ tất cả dữ liệu của 3 hình ảnh vào một file duy nhất, chúng ngăn cách nhau bởi "@@@". Làm sao để đọc file này và ghi ra 3 file hình ảnh tương ứng với các dữ liệu?

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

Sử dụng PushbackInputStream để đọc nội dung của file dữ liệu nói trên. Khi bắt gặp byte 64 ( @ ) bạn cần đọc 2 bytes tiếp theo để quyết định cần phải làm gì với byte hiện tại.
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
Việc sử dụng một InputStream thông thường để đọc từng byte sẽ tốn rất nhiều thời gian, bạn nên sử dụng BufferedInputStream cải tiến hiệu suất của ví dụ trên:
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();
    }
}

Xem thêm các chuyên mục: