Java - 了解 PrintWriter 和刷新需求
Java - Understanding PrintWriter and need for flush
好的,首先我为所有代码道歉,但我觉得代码太多总比不够好。我正在制作一个简单的聊天客户端和印刷机,尤其是我正在苦苦挣扎。使用代码的方式,现在它将与服务器交互 class 并且非常好并打印我想要打印的内容。但是,当我删除 '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();
}
}
提前致谢,如果我能提供更多信息,请在我已正确发布到 Whosebug 的第一时间告诉我。
不在每个 println
之后刷新数据更有效。如果您正在写入大量数据,您希望对其进行缓冲并大块发送,而不是单独发送每一行。这就是为什么如果你想确保数据确实发送到另一端,你需要手动刷新流。
想象一下,您正在给朋友写一封电子邮件,您将每个单词作为单独的电子邮件发送,而不是将整个文本发送到一封电子邮件中。你觉得哪个更快?当然,如果您按自己的想法发送每个单词,您的朋友会更快地阅读邮件,但总花费的时间会变长。
PrintWriter
class "commit" 的 println()
方法仅在 autoFlush
属性启用时将数据传输到流中。
看看 Java 文档中的这句话:
if automatic flushing is enabled it will be done only when one of the println, printf, or format methods is invoked
Link 到 Java 文档:https://docs.oracle.com/javase/7/docs/api/java/io/PrintWriter.html#PrintWriter(java.io.OutputStream,%20boolean)
如果您需要将消息发送到服务器,请创建 PrintWriter
对象并打开自动刷新选项。
因此,在创建 writer
对象的地方,只需执行以下操作:
writer = new PrintWriter(sock.getOutputStream(), true);
应该可以了。希望对您有所帮助!
好的,首先我为所有代码道歉,但我觉得代码太多总比不够好。我正在制作一个简单的聊天客户端和印刷机,尤其是我正在苦苦挣扎。使用代码的方式,现在它将与服务器交互 class 并且非常好并打印我想要打印的内容。但是,当我删除 '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();
}
}
提前致谢,如果我能提供更多信息,请在我已正确发布到 Whosebug 的第一时间告诉我。
不在每个 println
之后刷新数据更有效。如果您正在写入大量数据,您希望对其进行缓冲并大块发送,而不是单独发送每一行。这就是为什么如果你想确保数据确实发送到另一端,你需要手动刷新流。
想象一下,您正在给朋友写一封电子邮件,您将每个单词作为单独的电子邮件发送,而不是将整个文本发送到一封电子邮件中。你觉得哪个更快?当然,如果您按自己的想法发送每个单词,您的朋友会更快地阅读邮件,但总花费的时间会变长。
PrintWriter
class "commit" 的 println()
方法仅在 autoFlush
属性启用时将数据传输到流中。
看看 Java 文档中的这句话:
if automatic flushing is enabled it will be done only when one of the println, printf, or format methods is invoked
Link 到 Java 文档:https://docs.oracle.com/javase/7/docs/api/java/io/PrintWriter.html#PrintWriter(java.io.OutputStream,%20boolean)
如果您需要将消息发送到服务器,请创建 PrintWriter
对象并打开自动刷新选项。
因此,在创建 writer
对象的地方,只需执行以下操作:
writer = new PrintWriter(sock.getOutputStream(), true);
应该可以了。希望对您有所帮助!