Java - 了解PrintWriter并需要刷新

时间:2016-08-30 11:03:21

标签: java io stream printwriter

好的,首先我为所有代码道歉,但我觉得太多的代码比不够好。我正在制作一个简单的聊天客户端和编剧,特别是我正在努力。使用代码的方式现在它将与服务器类进行交互,并且非常精细并打印出我想要打印的内容。但是,当我删除'writer.flush();'它会停止打印。凭借我的理解 - 这显然是错误的 - 'writer.println(outgoing.getText());'应该足够了,因为这会发送我试图发送到服务器的文本。我理解flush会强制写入所有信息,但为什么在我写完我想写的内容时需要这样做?

public class SimpleChatClientA {

JTextArea incoming;
JTextField outgoing;
BufferedReader reader;
PrintWriter writer;
Socket sock;

public void go(){

    JFrame frame = new JFrame("Ludicrously Simple Chat Client");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    JPanel mainPanel = new JPanel();

    incoming = new JTextArea(15,50);
    incoming.setLineWrap(true);
    incoming.setWrapStyleWord(true);
    incoming.setEditable(false);

    JScrollPane qScroller = new JScrollPane(incoming);
    qScroller.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
    qScroller.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);

    outgoing = new JTextField(20);

    JButton sendButton = new JButton("Send");
    sendButton.addActionListener(new SendButtonListener());

    mainPanel.add(qScroller);
    mainPanel.add(outgoing);
    mainPanel.add(sendButton);
    setUpNetworking();

    Thread readerThread = new Thread(new IncomingReader());
    readerThread.start();

    frame.getContentPane().add(BorderLayout.CENTER, mainPanel);
    frame.setSize(400, 500);
    frame.setVisible(true);


}//close go

public void setUpNetworking(){
    try{

        sock = new Socket("127.0.0.1", 5000);

        InputStreamReader streamReader = new InputStreamReader(sock.getInputStream());

        reader = new BufferedReader(streamReader);
        writer = new PrintWriter(sock.getOutputStream());
        System.out.println("network established");
    }catch(Exception e){
        e.printStackTrace();
    }
}//close setupnetworking

public class SendButtonListener implements ActionListener{

    @Override
    public void actionPerformed(ActionEvent e) {

        try{
            writer.println(outgoing.getText());
            writer.flush();
        }catch(Exception ex){
            ex.printStackTrace();
        }
        outgoing.setText("");
        outgoing.requestFocus();
    }

}//close sendbuttonlistener inner class


public class IncomingReader implements Runnable{

    public void run(){
        String message;
        try{

            while((message = reader.readLine()) != null){
                System.out.println("read " + message);
                incoming.append(message + "\n");
            }

        }catch(Exception e){
            e.printStackTrace();
        }
    }

}//close inner class incomingreader


public static void main(String[] args){
    new SimpleChatClientA().go();
}

}

在此先感谢,如果我能提供更多信息,请第一时间让我知道我已正确发布到stackoverflow。

2 个答案:

答案 0 :(得分:1)

在每个println之后不刷新数据会更有效率。如果您正在编写大量数据,则需要缓冲它并发送大块数据,而不是单独发送每一行。这就是为什么你需要手动刷新流,如果你想确保数据确实发送到另一端。

想象一下,您正在给朋友写一封电子邮件,并将每个单词作为自己的电子邮件发送,而不是通过一封电子邮件发送整个文本。您认为哪个更快?当然,如果您按照自己的想法发送每个单词,您的朋友将会更快地阅读邮件,但所用的总时间会变得更长。

答案 1 :(得分:1)

println()类的PrintWriter方法"提交"仅在启用autoFlush属性时才将数据添加到流中。

请参阅Java文档中的这句话:

  

如果启用了自动刷新,则只有在调用println,printf或format方法之一时才会执行此操作

此处链接到Java文档:https://docs.oracle.com/javase/7/docs/api/java/io/PrintWriter.html#PrintWriter(java.io.OutputStream,%20boolean)

如果您需要将消息发送到服务器,请在打开autoflush选项的情况下创建PrintWriter对象。

因此,在您创建writer对象的位置,只需执行以下操作:

writer = new PrintWriter(sock.getOutputStream(), true);

应该这样做。希望它有所帮助!