2016-04-13 87 views
3

我在我的小演示程序中有一個服務器和客戶端,我將一些字符串數據從客戶端發送到服務器,然後爲客戶端重新發送此數據,並將其寫入控制檯。我對PrtintWriter的flush方法感到困惑,這是根據JAVA文檔,刷新流。經過一番研究後,我開始熟悉自動閃光的概念:當autoFlash參數爲true時,println,printf或format方法將刷新輸出緩衝區。我唯一不理解的是爲什麼我應該在循環中使用PrintWriter的flush方法,而不是在循環之後。 (在我的情況下,我在服務器端使用PrintWriter。)自動閃光執行相同的操作,因爲println()方法也在循環中。當我在循環後使用flush時,我的字符串數據不會出現在控制檯上。感謝您提前給予指導和幫助!在PrintWriter的情況下,爲什麼我應該在循環中沖洗而不是在循環之後沖洗?

客戶:

public class ClientDemo { 
public static void main(String[] args) throws IOException { 

    final String CLIENTNAME = "<CLIENT>:"; 
    final String SERVERADDRESS = "localhost"; 
    final int PORT = 12312; 

    try { 
     Socket socket = new Socket(SERVERADDRESS, PORT); 
     PrintWriter out = 
      new PrintWriter(socket.getOutputStream(), true);     
     Scanner scanner = new Scanner(socket.getInputStream()); 

     System.out.println(CLIENTNAME + "Client starts"); 
     List<String> lista = getList(); 

     for(String userInput : lista){ 
      out.println(userInput); 
      System.out.println("echo: " + scanner.nextLine()); 
     } 

    } catch(IOException e) { 
     System.out.println(CLIENTNAME + "Error connecting to the server:" + e.getMessage()); 
    } 
} 

    private static List<String> getList(){ 
     List<String> result = new ArrayList<>(); 
     result.add("egy"); 
     result.add("ketto"); 
     result.add("harom"); 
     result.add("negy"); 

     result.add("ot"); 
     result.add("hat"); 
     result.add("het"); 
     result.add("nyolc"); 
     result.add("kilenc"); 
     result.add("tiz"); 

     return result; 
    } 
} 

服務器:

public class ServerDemo { 
public static void main(String args[]) throws IOException { 

    final int PORT = 12312; 
    final String SERVERNAME ="<SERVER>:"; 

    try { 
     ServerSocket serverSocket = new ServerSocket(PORT); 
     Socket socket = serverSocket.accept(); 
     PrintWriter printWriter = new PrintWriter(socket.getOutputStream()); 
     Scanner scanner = new Scanner(socket.getInputStream()); 

     System.out.println(SERVERNAME + "Server starts..."); 

     String inputLine; 
     while(scanner.hasNext()) { 
      inputLine = scanner.nextLine(); 
      printWriter.println(inputLine); 
      printWriter.flush(); 
     } 

    } catch (IOException e) { 
     System.out.println(SERVERNAME + "Error handleing client..."); 
    } 
    } 
} 

回答

2

你不必寫每一行之後調用平齊。這樣做可以阻止I/O。通過調用flush可以確保寫入套接字的每一行都是實際寫入的,而不僅僅是緩衝(稍後寫入)。緩衝提高了I/O性能。但在這裏,似乎由於某些原因,您沒有利用緩衝帶來的好處。在寫入完成之前,您正在阻止。

+0

首先感謝您的回答。其次,你能否給我一個關於如何通過在循環中刷新來阻止I/O的更深入的解釋?因爲如果我刪除刷新行,字符串列表不會出現在控制檯中。我的老師還警告我使用沖洗方法。正如你所看到的,我沒有使用autofalsh或在我的例子中關閉。再次提前謝謝你! – F3R1

+1

你應該嘗試在catch塊後面的finally塊中關閉PrintWriter對象。現在你不關閉PrintWriter資源。如果您關閉資源,它也會在關閉資源之前將其刷新。此時,緩衝區中的所有行將被刷新(寫入)到目標。嘗試添加一個finally塊並關閉PrintWriter資源。您應該在控制檯上看到輸出。您還可以使用新的Java 7 try-with-resources語句,以便不必關閉實現AutoClosable接口的任何資源。 – VHS

+0

如果我關閉finally塊中的資源,並從代碼中移除刷新或在循環之後移動它,不幸的是它也會執行相同的錯誤,並且我無法在控制檯上看到輸出。我知道try-with-resource語句,我用它重寫代碼,併發生相同的症狀。如果flush在循環中,則輸出在控制檯上...如果它從循環中移除或在循環後我看不到輸出。 (順便說一句,我很感謝你的幫助,我已經給了你投票權,當我獲得魔法般的高聲望後,你會看到這個:)。) – F3R1