Tags:

Luồng dữ liệu ngầm PipedInputStream và PipedOutputStream trong java

Pipes trong java IO cung cấp khả năng giao tiếp giữa 2 luồng (thread) chạy trên cùng JVM.

PipedInputStream-PipedOutputStream

Giả sử bạn có 2 luồng, A là luồng dữ liệu đầu vào và B là luồng dữ liệu đầu ra. Hai luồng này chạy trên 2 thread khác nhau vậy làm sao để kết nối A và B lại với nhau?

Trong java cung cấp 2 class PipedInputStream đại diện cho luồng dữ liệu đầu vào và PipedOutputStream đại diện cho luồng dữ liệu đầu ra, chúng có thể kết nối với nhau và tự hiểu ngầm ra “tao ghi dữ liệu cho mày – Tao đọc dữ liệu từ mày”.

import java.io.IOException;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;

class PipeExample {

    public static void main(String[] args) throws IOException {

        final PipedOutputStream output = new PipedOutputStream();
        final PipedInputStream input  = new PipedInputStream(output);


        Thread thread1 = new Thread(() -> {
            try {
                output.write("Hello world, pipe!".getBytes());
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    output.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        });


        Thread thread2 = new Thread(() -> {
            try {
                System.out.println("I'm thread 2");
                int data = input.read();
                while(data != -1){
                    System.out.print((char)data);
                    data = input.read();
                }
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    input.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        });

        thread1.start();
        thread2.start();

    }
}

Output:

I’m thread 2
Hello world, pipe!

Connect trong PipedInputStream và PipedOutputStream

Trong trường hợp tại thời điểm khởi tạo chúng ta chưa xác định điểm PipedOutputStream và PipedInputStream nào sẽ kết nối với nhau thì chúng ta có thể sử dụng method connect() để liên kết chúng lại với nhau. 

Note: Cả PipedInputStream và PipedOutputStream đều có method connect() chúng ta có thể sử dụng một trong hai đều có tác dụng như nhau. 

import java.io.IOException;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;

class PipeExample {

    public static void main(String[] args) throws IOException {

        PipedInputStream input = new PipedInputStream();
        PipedOutputStream output = new PipedOutputStream();
        try {
            // Use of connect() : connecting input with output
//            output.connect(input);
            input.connect(output);

            output.write(65);
            output.write(66);
            output.write(67);
            output.write(68);
            output.write(69);
            output.write(70);

            // Use of available() :
            System.out.println("Use of available() : " + input.available());

            // Use of read(byte[] buffer, int offset, int maxlen) :
            byte[] buffer = new byte[5];
            // destination 'buffer'
            input.read(buffer, 0, 5);

            String str = new String(buffer);
            System.out.println("Using read(buffer, offset, maxlen) : " + str);

            // USe of close() method :
            System.out.println("Closing the stream");
            input.close();

        } catch (IOException excpt) {
            excpt.printStackTrace();
        } finally {
            try {
                input.close();
                output.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

Output:

Use of available() : 6
Using read(buffer, offset, maxlen) : ABCDE
Closing the stream

Các method trong PipedInputStream

PipedInputStream đại diện cho luồng dữ liệu đầu vào chứa các method phục vụ cho việc đọc dữ liệu từ PipedOutputStream.

int read() – Đọc byte tiếp theo từ PipedInputStream. Giá trị byte nằm trong khoảng 0 – 255. Trả về -1 để thông báo rằng đã đọc hết dữ liệu trong PipedInputStream.

int read(byte[] buffer, int offset, int maxlen) – Đọc dữ liệu từ PipedInputStream bắt đầu tại vị trí offset và đọc tối đa maxlen.

public int read(byte[] buffer, int offset, int maxlen)
Parameters : 
buffer : Nơi chứa dữ liệu được đọc vào
offset : Vị trí đầu tiên được lưu trữ trong buffer
maxlen : Số lượng ký byte tối đa được đọc
Return : Trả về số lượng byte đọc được                                               
return -1 Nếu không còn dữ liệu để đọc 

> IOException : Trong trường hợp xảy ra lỗi IO.
-> NullPointerException : Nếu buffer rỗng
-> IndexOutOfBoundsException : Nếu offset âm hoặc maxlen > b.length - offset
import java.io.IOException;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;

class PipeExample {

    public static void main(String[] args) throws IOException {

        PipedInputStream input = new PipedInputStream();
        PipedOutputStream output = new PipedOutputStream();
        try {
            // Use of connect() : connecting input with output
            input.connect(output);

            output.write(65);
            output.write(66);
            output.write(67);
            output.write(68);
            output.write(69);
            output.write(70);

            // Use of read(byte[] buffer, int offset, int maxlen) :
            byte[] buffer = new byte[5];
            // destination 'buffer'
            input.read(buffer, 2, 2);

            String str = new String(buffer);
            System.out.println("Using read(buffer, offset, maxlen) : " + str);

            input.close();

        } catch (IOException excpt) {
            excpt.printStackTrace();
        } finally {
            try {
                input.close();
                output.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }
}

Output: Using read(buffer, offset, maxlen) : __AB_

Sau khi mình chọn offset là 2 thì 2 vị trí đầu tiên của mảng rỗng, và đọc tối đa maxlen là 2 ký tự AB.

void close() – Đóng các kết nối của PipedInputStream đến các tài nguyên mà nó đang tham chiếu đến.

int available() – Trả về số byte còn lại có thể đọc được từ PipedInputStream.

Các method trong PipedOutputStream

PipedOutputStream đại diện cho luồng dữ liệu đầu ra chứa các method phục vụ cho ghi dữ liệu vào PipedInputStream.

void write(int byte) – Ghi dữ liệu từng byte một vào PipedInputStream.

void write(byte[] buffer, int offset, int maxlen) – Ghi tối đa maxlen byte bắt đầu từ vị trí offset trong mảng buffer vào PipedInputStream.

import java.io.IOException;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;

class PipeExample {

    public static void main(String[] args) {
        PipedInputStream input = new PipedInputStream();
        PipedOutputStream output = new PipedOutputStream();

        try {
            // Use of connect() : connecting geek_input with geek_output
            input.connect(output);

            byte[] buffer = {'J', 'A', 'V', 'A'};

            // Use of write(byte[] buffer, int offset, int maxlen)
            output.write(buffer, 0, 4);
            int a = 5;
            System.out.print("Use of write(buffer, offset, maxlen) : ");
            while (a > 0) {
                System.out.print(" " + (char) input.read());
            }

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                input.close();
                output.close();
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
    }
}

void close() – Đóng kết nối giữa PipedOutputStream với các tài nguyên khác.

void connect(PipedInputStream input) – Kết nối PipedOutputStream với PipedInputStream.

void flush() – Đẩy dữ liệu xuống PipedInputStream. Trong trường hợp bạn write() dữ liệu xuống vì các mục đích khác nhau như hiệu xuất etc mà dữ liệu chưa được ghi xuống PipedInputStream, sử dụng flush() để đẩy dữ liệu xuống

import java.io.IOException;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;

import java.io.IOException;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;

class PipeExample {

    public static void main(String[] args) throws IOException {
        PipedInputStream input = new PipedInputStream();
        PipedOutputStream output = new PipedOutputStream();
        try {
            // Use of connect() : connecting geek_input with geek_output
            input.connect(output);

            // Use of write(int byte) :
            output.write(65);
            output.write(66);
            output.write(67);
            output.write(68);
            output.write(69);

            // Use of flush() method :
            output.flush();
            System.out.println("Use of flush() method : ");

            int i = 5;
            while (i > 0) {
                System.out.print(" " + (char) input.read());
                i--;
            }

            // USe of close() method :
            System.out.println("\nClosing the Output stream");

        } catch (IOException excpt) {
            excpt.printStackTrace();
        } finally {
            try {
                input.close();
                output.close();
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
    }
}

Output:

Use of flush() method :
A B C D E
Closing the Output stream

Nguồn tham khảo:

https://docstore.mik.ua/orelly/java/exp/ch08_01.htm

https://www.geeksforgeeks.org/java-io-pipedoutputstream-class-java/

0 0 votes
Article Rating
Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x