整理 Java I/O (五):管道流 - PipedInput/OutputStream、PipedReader/Writer

Java IO中的管道为运行在同一个JVM中的两个线程提供了通信的能力。所以管道流也可以作为数据源和目标媒介。

在Java 中,通信的双方应该是在同以进程中的不同线程。一个管道输出流应该和一个管道输入流配合使用,通过connect()方法使之关联,一个线程通过输出流写入的数据可以被另一个线程通过关联的输入流读取出来。

管道输入流中有一个2014字节大小的缓冲区,管道输出流写出的数据实际上是保存到了与之相连接的管道输入流的内部缓冲区只能够。输入流执行read操作的时候,实际上是读取的该缓冲区内的数据。如果缓冲区满了,则不再写入数据,管道输出流所在的线程也会被阻塞,直到管道输入流从缓冲区中读取数据。

当使用两个相关联的管道流时,需要将他们分配给不同的线程,假如输入和输出流处于同一个线程,那么当缓冲区满了之后,则线程阻塞,那么输入流也无法去读取缓冲区内容,所以如果在同一个线程中使用,可能会造成线程死锁。如果某个线程不再处于活动状态,那么线程中管道流则处于毁坏状态。

Java 中的管道流和其他流一样,也分为输入流和输出流,也分为字节管道和字符管道,如下所示:

  • PipedInputStream

  • PipedOutputStream

  • PipedReader

  • PipedWriter

PipedInputStream

构造方法

  • PipedInputStream()

    创建尚未连接的 PipedInputStream。

  • PipedInputStream(int pipeSize)

    创建一个尚未连接的 PipedInputStream,并对管道缓冲区使用指定的管道大小。

  • PipedInputStream(PipedOutputStream src)

    创建 PipedInputStream,使其连接到管道输出流 src。

  • PipedInputStream(PipedOutputStream src, int pipeSize)

    创建一个 PipedInputStream,使其连接到管道输出流 src,并对管道缓冲区使用指定的管道大小。

其他方法

  • available()

    返回可以不受阻塞地从此输入流中读取的字节数。

  • close()

    关闭此管道输入流并释放与该流相关的所有系统资源。

  • connect(PipedOutputStream src)

    使此管道输入流连接到管道输出流 src。

  • read()

    读取此管道输入流中的下一个数据字节。

  • read(byte[] b, int off, int len)

    将最多 len 个数据字节从此管道输入流读入 byte 数组。

PipedOutputStream

构造方法

  • PipedOutputStream()

    创建尚未连接到管道输入流的管道输出流。

  • PipedOutputStream(PipedInputStream snk)

    创建连接到指定管道输入流的管道输出流。

其他方法

  • close()

    关闭此管道输出流并释放与此流有关的所有系统资源。

  • connect(PipedInputStream snk)

    将此管道输出流连接到接收者。

  • flush()

    刷新此输出流并强制写出所有缓冲的输出字节。

  • write(byte[] b, int off, int len)

    将 len 字节从初始偏移量为 off 的指定 byte 数组写入该管道输出流。

  • write(int b)

    将指定 byte 写入传送的输出流。

调用PipedInputStream和PipedOutputStream的connect方法效果一样

PipedReader

构造方法

  • PipedReader()

    创建尚未连接的 PipedReader。

  • PipedReader(int pipeSize)

    创建一个尚未连接的 PipedReader,并对管道缓冲区使用指定的管道大小。

  • PipedReader(PipedWriter src)

    创建连接到传送 writer src 的 PipedReader。

  • PipedReader(PipedWriter src, int pipeSize)

    创建一个 PipedReader,使其连接到管道 writer src,并对管道缓冲区使用指定的管道大小。

其他方法

  • close()

    关闭此传送流并释放与该流相关的所有系统资源。

  • connect(PipedWriter src)

    使此传送 reader 连接到传送 writer src。

  • read()

    读取此传送流中的下一个数据字符。

  • read(char[] cbuf, int off, int len)

    将此传送流中最多 len 个数据字符读入字符数组。

  • ready()

    告知是否准备读取此流。

PipedWriter

构造方法

  • PipedWriter()

    创建一个尚未连接到传送 reader 的传送 writer。

  • PipedWriter(PipedReader snk)

    创建传送 writer,使其连接到指定的传送 reader。

其他方法

  • close()

    关闭此管道输出流并释放与此流相关的所有系统资源。

  • connect(PipedReader snk)

    将此传送 writer 连接到接收方。

  • flush()

    刷新此输出流并强制写出所有缓冲的输出字符。

  • write(char[] cbuf, int off, int len)

    将 len 字符从指定初始偏移量为 off 的字符数组写入到此管道输出流。

  • write(int c)

    将指定的 char 写入管道输出流。

调用PipedWriter和PipedReader的connect方法效果一样

简单示例

public class PipedStreamTest {

    private PipedInputStream pis;
    private PipedOutputStream pos;

    private PipedWriter writer;
    private PipedReader reader;

    public static void main(String[] args) {
        new PipedStreamTest().testBytePiped();
        new PipedStreamTest().testCharPiped();
    }

    private void testBytePiped() {

        try {
            pis = new PipedInputStream();
            pos = new PipedOutputStream();
            pis.connect(pos);
        } catch (IOException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }

        Thread writeThread = new Thread(new Runnable() {

            @Override
            public void run() {
                try {
                    pos.write("This is a string for PipedInputStream/PipedOutputStream"
                            .getBytes());
                    pos.flush();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } finally {
                    try {
                        if (pos != null) {
                            pos.close();
                        }
                    } catch (IOException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            }
        });
        Thread readThread = new Thread(new Runnable() {

            @Override
            public void run() {
                try {
                    int i = 0;
                    while ((i = pis.read()) != -1) {
                        System.out.print((char) i);
                    }
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        });

        writeThread.start();
        readThread.start();
    }

    private void testCharPiped() {

        try {
            reader = new PipedReader();
            writer = new PipedWriter();
            writer.connect(reader);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        Thread writeThread = new Thread(new Runnable() {

            @Override
            public void run() {
                try {
                    writer.write("This is a string for PipedReader/PipedWriter");
                    writer.flush();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } finally {
                    try {
                        if (writer != null) {
                            writer.close();
                        }
                    } catch (IOException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            }
        });

        Thread readThread = new Thread(new Runnable() {

            @Override
            public void run() {
                try {

                    System.out.println();
                    int length = 0;
                    char[] arr = new char[2];
                    while ((length = reader.read(arr)) != -1) {
                        System.out.print(new String(arr, 0, length));
                    }
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } finally {
                    try {
                        if (reader != null) {
                            reader.close();
                        }
                    } catch (IOException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            }
        });
        readThread.start();
        writeThread.start();
    }
}
Copyright© 2020-2022 li-xyz 冀ICP备2022001112号-1