2012-12-05 33 views
2

我編寫了一個Java CLI程序,它從stdin讀取行併爲每行輸出一個可能的完成。我試圖給它一個gui,所以我試圖建立一個System.in的drop-in替換,以允許用戶使用gui或cli。System.in和自定義InputStreamReader之間的行爲差​​異

到目前爲止,我得到這個置換,其方法add當文本在JTextArea輸入被稱爲:

import java.io.BufferedReader; 
import java.io.IOException; 
import java.io.InputStream; 
import java.io.InputStreamReader; 
import java.io.InterruptedIOException; 
import java.util.LinkedList; 
import java.util.concurrent.LinkedBlockingQueue; 
import java.util.concurrent.TimeUnit; 

public class GuiIn extends InputStream { 

    protected LinkedBlockingQueue<Byte> buf; 
    protected boolean closed; 

    public GuiIn() { 
     closed = false; 
     buf = new LinkedBlockingQueue<Byte>(); 
    } 

    @Override 
    public void close() { 
     closed = true; 
    } 

    /** 
    * add strings to read in the InputStream. Arguments are ignored if the 
    * stream is closed. 
    * 
    * @param s 
    *   a string. Ignored if null 
    */ 
    public void add(String s) { 
     if (closed || s == null) { 
      return; 
     } 
     byte[] bs = s.getBytes(); 
     LinkedList<Byte> lbs = new LinkedList<Byte>(); 
     for (byte b : bs) { 
      lbs.add(b); 
     } 
     buf.addAll(lbs); 
    } 

    @Override 
    public int available() { 
     return buf.size(); 
    } 

    @Override 
    public synchronized int read() throws InterruptedIOException { 
     if (closed && buf.isEmpty()) { 
      return -1; 
     } 
     Byte b = 0; 

     while (true) { 
      try { 

       if ((b = buf.poll(100, TimeUnit.MILLISECONDS)) == null) { 
        if (closed && buf.isEmpty()) 
         return -1; 
       } else 
        break; 

      } catch (InterruptedException e) { 
       throw new InterruptedIOException("interrupted: " 
         + e.getMessage()); 
      } 
     } 
     return b; 
    } 
} 

然而,當我嘗試它與new BufferedReader(new InputStreamReader(in));並試圖readLine()它,它似乎直到它有足夠的字符(很多),儘管文本饋送總是由我的聽衆附加一個換行符。

另一方面,如果in設置爲System.in,則每輸入一行就會讀取一行。

所以,我的問題有兩個部分:

  1. 哪裏這種差異從何而來?
  2. 如何解決?

請注意,從每字節裸GuiIn字節讀取正常工作,而且我已經嘗試過像減少BufferedReader的緩衝區的大小技巧。

我也在網上預先搜索過:這不是關於創建一個模擬對象;而ByteArrayInputStream也不是一個選項:它不支持追加。你的問題的

回答

2

來源之一可能是InputStreamReader可以閱讀遠一點,以便它可以確保byte堅持 - 它使用>char解碼器(和它是不透明的話)有足夠的字節來產生一個完整charSystem.in可能足夠了解默認編碼以提供足夠的字節。

在開始使用Java進行交互式控制檯工作之前,您應該熟悉Console類和readline to Java端口。

然後,不是沒有指定的編碼創建InputStreamReader S,我會抽象在更高層次上:

interface CommandLineSource { 
    String readLine() throws IOException; 
} 

,然後你可以創建一個由FileDescriptor.STDIN的支持,另一個通過任何你喜歡讓您可以自動輸入以進行測試。

+0

好主意抽象圍繞這個問題,雖然這是一個多態性讓步。使用控制檯似乎不太合適,因爲當流重定向時,文檔不能保證存在控制檯(我打算執行批處理來分析許多完成項)。有一件事:這不是關於測試:我已經有JUnit類直接與完成類交互。無論如何,感謝指針! –

+1

@bernardpaulus,是的。這是讓人失望的。我知道默認的'System.out'做了很多非常特定於操作系統的guff,可以用作字節和字符接收器,我懷疑'System.in'類似。如果你抽象,那麼你可以在可用的地方使用'Console',但是當'System.console()== null'時,你可以回到緩衝讀取器周圍的簡單包裝。 –

+0

事實上,它是導致問題的解碼器:openjdk-6的行爲與官方sdk(java 6)的行爲相同,並且通過查看openjdk的源代碼進行了確認。沒有完全通過確切的解碼器類,但那是另一次。再次感謝! –

相關問題