Java - Understanding PrintWriter and need for flus

2019-03-01 03:49发布

Ok, firstly I apologise for all the code but I feel like too much code is better than not enough. I'm making a simple chat client and printwriter in particular i'm struggling with. With the code the way it is the now it will interact with the server class and perfectly fine and print what im wanting to print. However, when I remove 'writer.flush();' it will stop printing. With my understanding -which is evidently wrong- 'writer.println(outgoing.getText());' should be enough as this would send the text im trying to send to the server. I understand flush forces all the information to write but why is this required when i've already written what I want to write?

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();
}

}

Thanks in advance, if there is anymore information I can give please let me know first time i've properly posted to stackoverflow.

2条回答
相关推荐>>
2楼-- · 2019-03-01 04:24

The println() methods of the PrintWriter class "commit" the data to the stream only if the autoFlush attribute is enabled.

Look at this quote from the Java docs:

if automatic flushing is enabled it will be done only when one of the println, printf, or format methods is invoked

Link to Java docs here: https://docs.oracle.com/javase/7/docs/api/java/io/PrintWriter.html#PrintWriter(java.io.OutputStream,%20boolean)

If you need to send the message over to the server, then create the PrintWriter object with the autoflush option turned on.

So, where you're creating the writer object, just do this:

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

That should do it. Hope it helps!

查看更多
一夜七次
3楼-- · 2019-03-01 04:48

It's more efficient not to flush the data after every single println. If you're writing a lot of data, you want to buffer it and send in big chunks, not send each line separately. That's why you need to manually flush the streams if you want to make sure that the data is indeed sent to the other end.

Imagine you're writing an email to a friend, and you send each word as its own email vs. sending the whole text in a single email. Which do you think is faster? Sure, your friend will get to read the mail quicker if you send each word as you think of it, but the total time taken will become longer.

查看更多
登录 后发表回答