2016-08-30 5 views
1

Хорошо, во-первых, я прошу прощения за весь код, но я чувствую, что слишком много кода лучше, чем недостаточно. Я делаю простой чат-клиент и печатник, в частности, я борется. С кодом так, как сейчас, он будет взаимодействовать с классом сервера и прекрасно работать и печатать то, что им нужно распечатать. Однако, когда я удаляю 'writer.flush();' он прекратит печать. С моим пониманием, которое, очевидно, неверно, - writer.println (outgoing.getText()); должно быть достаточно, поскольку это отправит текст im, пытающийся отправить на сервер. Я понимаю, что flush заставляет всю информацию писать, но почему это требуется, когда я уже написал то, что хочу написать?Java - Понимание PrintWriter и необходимость в флеше

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.

ответ

1

Методы класса PrintWriter «зафиксировать» данные в потоке, только если включен атрибут autoFlush.

Посмотрите на это цитата из документации Java:

если автоматическая промывка включена, это будет сделано только тогда, когда один из Println, Printf или методы форматирования вызывается

Ссылка Java docs здесь: 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);

Это должно сделать это. Надеюсь, поможет!

+0

Ahh ok thanks Я прочитал документы, но по какой-то причине это было не совсем щелкнуть, а просто расширилось, объяснив, что это очень помогло. Благодаря ! – fdbdcbc

1

Более эффективно не очищать данные после каждого println. Если вы пишете много данных, вы хотите их буферировать и отправлять большие куски, а не отправлять каждую строку отдельно. Вот почему вам необходимо вручную очистить потоки, если вы хотите убедиться, что данные действительно отправлены на другой конец.

Представьте, что вы пишете электронное письмо другу, и вы отправляете каждое слово как свое собственное электронное письмо или отправляете весь текст в одном электронном письме. Как вы думаете, что быстрее? Конечно, ваш друг быстрее прочитает почту, если вы отправите каждое слово, как вы думаете об этом, но общее время будет больше.

+0

Спасибо, но если мне нужно использовать флеш для отправки данных после каждого println, что на самом деле делает println? Я думал, что println отправил данные через поток? Java-документы говорят, что он печатает строку, но где именно она ее печатает? – fdbdcbc

+0

В буфер. Если буфер заполнен, он загорается. Если он не заполнен, он еще не покраснел. – Kayaman

+0

Ahh ok Я никогда не понимал, что у PrintWriter есть буфер, теперь имеет смысл! – fdbdcbc