Java PipedWriter类

PipedWriter 是字符管道输出流,它继承于Writer,它用于将当前线程的指定字符写入到与此线程对应的管道字符输入流中去、所以PipedReader、PipedWriter必须配套使用、缺一不可。管道字符输出流的本质就是调用PipedReader中的方法将字符或者字符数组写入到PipedReader中、这一点是与众不同的地方。所以pw中的方法很少也很简单、主要就是负责将传入的pr与本身绑定、配对使用、然后就是调用绑定的PipedReader的写入方法、将字符或者字符数组写入到PipedReader的缓存字符数组中。

构造函数

PipedWriter(PipedReader snk)    根据传入的PipedReader构造PipedWriter、并将PipedReader与此PipedWriter绑定  
PipedWriter()    创建一个PipedWriter、在使用之前必须与一个PipedReader绑定  

关键字

private PipedReader sink;   与此PipedWriter绑定的PipedReader  
private boolean closed = false;     标示此流是否关闭。  

方法

synchronized void connect(PipedReader snk)      将此PipedWriter与一个PipedReader绑定  
void close()    关闭此流。  
synchronized void connect(PipedReader snk)      将此PipedWriter与一个PipedReader绑定  
synchronized void flush()   flush此流、唤醒PipedReader中所有等待的方法。  
void write(int c)   将一个整数写入到与此PipedWriter绑定的pr的缓存字符数组buf中去  
void write(char cbuf[], int off, int len)   将cbuf的一部分写入PipedReader的buf中去 

源码分析

public class PipedWriter extends Writer {  
      
    //与此PipedWriter绑定的PipedReader  
    private PipedReader sink;  
  
    //标示此流是否关闭。  
    private boolean closed = false;  
  
    /** 
     * 根据传入的PipedReader构造pw、并将pr与此pw绑定 
     */  
    public PipedWriter(PipedReader snk)  throws IOException {  
        connect(snk);  
    }  
      
    /** 
     * 创建一个pw、在使用之前必须与一个pr绑定 
     */  
    public PipedWriter() {  
    }  
      
    /** 
     * 将此pw与一个pr绑定 
     */  
    public synchronized void connect(PipedReader snk) throws IOException {  
        if (snk == null) {  
            throw new NullPointerException();  
        } else if (sink != null || snk.connected) {  
            throw new IOException("Already connected");  
        } else if (snk.closedByReader || closed) {  
                throw new IOException("Pipe closed");  
        }  
              
        sink = snk;  
        snk.in = -1;  
        snk.out = 0;  
        snk.connected = true;  
    }  
  
    /** 
     * 将一个整数写入到与此pw绑定的pr的缓存字符数组buf中去 
     */  
    public void write(int c)  throws IOException {  
        if (sink == null) {  
            throw new IOException("Pipe not connected");  
        }  
        sink.receive(c);  
    }  
  
    /** 
     * 将cbuf的一部分写入pr的buf中去 
     */  
    public void write(char cbuf[], int off, int len) throws IOException {  
        if (sink == null) {  
            throw new IOException("Pipe not connected");  
        } else if ((off | len | (off + len) | (cbuf.length - (off + len))) < 0) {  
            throw new IndexOutOfBoundsException();  
        }  
        sink.receive(cbuf, off, len);  
    }  
  
    /** 
     * flush此流、唤醒pr中所有等待的方法。 
     */  
    public synchronized void flush() throws IOException {  
        if (sink != null) {  
                if (sink.closedByReader || closed) {  
                    throw new IOException("Pipe closed");  
                }              
                synchronized (sink) {  
                    sink.notifyAll();  
                }  
        }  
    }  
  
    /** 
     * 关闭此流。 
     */  
    public void close()  throws IOException {  
        closed = true;  
        if (sink != null) {  
            sink.receivedLast();  
        }  
    }  
}

例子

PipedReader和PipedWriter与PipedInputStream和PipedOutputStream一样,都可以用于管道通信。PipedWriter是字符管道输出流,继承于Writer;PipedReader是字符管道输入流,继承于Reader,PipedWriter和PipedReader的作用是可以通过管道进行线程间的通讯。两者必须要配套使用。

1. Receiver

public class Receiver extends Thread {  
  
    // 管道输入流对象。  
    // 它和“管道输出流(PipedWriter)”对象绑定,  
    // 从而可以接收“管道输出流”的数据,再让用户读取。  
    private PipedReader in = new PipedReader();  
  
    // 获得“管道输入流对象”  
    public PipedReader getReader()  
    {  
        return in;  
    }  
  
    @Override  
    public void run(){  
        readMessageOnce() ;  
        //readMessageContinued() ;  
    }  
  
    // 从“管道输入流”中读取1次数据  
    public void readMessageOnce(){  
        // 虽然buf的大小是2048个字符,但最多只会从“管道输入流”中读取1024个字符。  
        // 因为,“管道输入流”的缓冲区大小默认只有1024个字符。  
        char[] buf = new char[2048];  
        try {  
            int len = in.read(buf);  
            System.out.println(new String(buf,0,len));  
            in.close();  
        } catch (IOException e) {  
            e.printStackTrace();  
        }  
    }  
  
    // 从“管道输入流”读取>1024个字符时,就停止读取  
    public void readMessageContinued()  
    {  
        int total=0;  
        while(true) {  
            char[] buf = new char[1024];  
            try {  
                int len = in.read(buf);  
                total += len;  
                System.out.println(new String(buf,0,len));  
                // 若读取的字符总数>1024,则退出循环。  
                if (total > 1024)  
                        break;  
                } catch (IOException e) {  
                    e.printStackTrace();  
                }  
        }  
  
        try {  
            in.close();  
        } catch (IOException e) {  
                e.printStackTrace();  
        }  
    }  
}

2. Sender

public class Sender extends Thread {  
    // 管道输出流对象。  
    // 它和“管道输入流(PipedReader)”对象绑定,  
    // 从而可以将数据发送给“管道输入流”的数据,然后用户可以从“管道输入流”读取数据。  
    private PipedWriter out = new PipedWriter();  
    // 获得“管道输出流”对象  
    public PipedWriter getWriter(){  
        return out;  
    }  
  
    @Override  
    public void run(){  
        writeShortMessage();  
        //writeLongMessage();  
    }  
  
    // 向“管道输出流”中写入一则较简短的消息:"this is a short message"   
    private void writeShortMessage() {  
        String strInfo = "this is a short message" ;  
        try {  
            out.write(strInfo.toCharArray());  
            out.close();  
        } catch (IOException e) {  
            e.printStackTrace();  
        }  
    }  
    // 向“管道输出流”中写入一则较长的消息  
    private void writeLongMessage() {  
        StringBuilder sb = new StringBuilder();  
        // 通过for循环写入1020个字符  
        for (int i=0; i<102; i++)  
            sb.append("0123456789");  
            // 再写入26个字符。  
            sb.append("abcdefghijklmnopqrstuvwxyz");  
            // str的总长度是1020+26=1046个字符  
            String str = sb.toString();  
        try {  
            // 将1046个字符写入到“管道输出流”中  
            out.write(str);  
            out.close();  
        } catch (IOException e) {  
            e.printStackTrace();  
        }  
    }  
}

3. test

public class PipeTest {  
    public static void main(String[] args) {     
        Sender t1 = new Sender();     
  
        Receiver t2 = new Receiver();     
  
        PipedWriter out = t1.getWriter();     
  
        PipedReader in = t2.getReader();  
        try {     
            //管道连接。下面2句话的本质是一样。  
            //out.connect(in);     
            in.connect(out);     
  
            /**   
            * Thread类的START方法:   
            * 使该线程开始执行;Java 虚拟机调用该线程的 run 方法。    
            * 结果是两个线程并发地运行;当前线程(从调用返回给 start 方法)和另一个线程(执行其 run 方法)。    
            * 多次启动一个线程是非法的。特别是当线程已经结束执行后,不能再重新启动。    
            */  
            t1.start();  
            t2.start();  
        } catch (IOException e) {  
             e.printStackTrace();  
        }  
    }  
}

输出结果:

this is a short message


版权声明:本文为JAVASCHOOL原创文章,未经本站允许不得转载。