2012-11-21 53 views
0

這裏是一個模擬InputStream模擬緩慢液流:如何以最小的延遲掃描緩慢的InputStream?

class SlowInputStream extends InputStream{ 
    private String internal = "5 6\nNext Line\n"; 
    private int position = 0; 

    @Override 
    public int available(){ 
     if(position==internal.length()) return 0; 
     else return 1; 
    } 

    @Override 
    public int read() throws IOException { 
     try { 
      Thread.sleep(1000); 
     } catch (InterruptedException e) { 
      throw new IOException("Sleep Interrupted"); 
     } 
     if(position==internal.length()) return -1; 
     return internal.charAt(position++); 

    } 

} 

在這裏被測試的代碼:

Scanner s = new Scanner(new SlowInputStream()); 

    int i=s.nextInt(); 
    System.out.println("i="+i); 
    int j=s.nextInt(); 
    System.out.println("j="+j); 
    s.nextLine(); 
    String line = s.nextLine(); 
    System.out.println("line="+line); 

    s.close(); 

上述代碼的行爲是它停止了一段時間,並打印三行。什麼樣的代碼可以輸出相同的東西,但是可以將行間的等待時間分開?

回答

-1

如果從InputStream創建Scanner,它將嘗試每次讀取特定數量的數據以提高性能。在我的機器中,金額是4096字節。這就是爲什麼在這個例子中,它總是一直等待,直到打印全部結果在同一時間。

要繞過這個緩存機制接口Readable應該使用而不是原始流。因爲沒有已知的實現可以這樣做,所以必須實現它們自己的實現。 (如果有人知道這樣的事請讓我知道),所以下面的代碼可以做的工作:

Scanner s = new Scanner(new Readable(){ 

    private InputStream is = new SlowInputStream(); 

    public int read(CharBuffer arg0) throws IOException { 
     int i = is.read(); 
     if(i>=0){ 
      arg0.append((char)i); 
      return 1; 
     } else return -1; 
    } 

}); 

int i=s.nextInt(); 
System.out.println("i="+i); 
int j=s.nextInt(); 
System.out.println("j="+j); 
s.nextLine(); 
String line = s.nextLine(); 
System.out.println("line="+line); 

s.close(); 

編輯:上述解決方案有一些缺點。首先它不關閉內部輸入流,因此存在泄漏。其次,這取決於字符集是單字節。它不適用於多字節字符集(即UTF-8)。爲了解決這些問題,我們可以使用一個ReadableByteChannel代替:

Scanner s = new Scanner(new ReadableByteChannel(){ 

    private InputStream is = new SlowInputStream(); 
    boolean isopen = true; 

    public int read(ByteBuffer arg0) throws IOException { 
     int i = is.read(); 
     if(i>=0){ 
      arg0.put((byte)i); 
      return 1; 
     } else return -1; 
    } 

    public void close() throws IOException { 
     isopen=false; 
     is.close(); 
    } 

    public boolean isOpen() { 
     return isopen; 
    } 

}); 

編輯:謝謝你的評論,我有固定的文字錯誤,並給出這個問題的更好的解釋。

+0

什麼'InputStream的默認緩存'你在說什麼?爲什麼Readable可以解決這個想象中的問題? – EJP

+0

我認爲這是一個錯誤。緩存實際上由'Scanner'使用。如果掃描器是從'InputStream'創建的,它將嘗試每次讀取特定數量(在我的情況下是4096字節)的數據。因此在這個例子中,它將繼續讀取,直到收到所有數據。通過使用「Readable」或「ReadableByteChannel」,只有在需要時,「Scanner」纔會讀取字節。 –

0

您還需要重寫read(byte [],int,int)。你最好擴展FilterInoutStream:這就是它的用途。

+0

重寫'read'是不夠的。 '掃描儀'將繼續調用它,直到它收到4096字節或到達我機器中流的末尾。這同樣適用於'FilterInoutStream'。 –