2014-09-06 29 views
1

我有一個簡單的測試應用程序,它連接到USB設備(作爲本地文件),傳輸開始傳輸字符,然後從設備讀取輸入。這一切工作正常,但很少會阻止read()調用。爲了防止這種情況,我試圖在繼續read()操作之前檢查是否至少有1個可用字節。但是,當我運行這個時,我從available()調用中得到一個IOException。BufferedInputStream的Java可用字節不工作

我的代碼是:

public static void testRecord() { 
    // Records data for a second 
    String portName = "\\\\.\\<DEVICE_FILE>"; 
    FileWriter out = null; 
    byte singleByte; 
    long startTime = System.currentTimeMillis(); 
    try { 

     out = new FileWriter(portName); 
     out.write('c');  // start data transmission 
     out.write(0x0d); // carriage return required 
     out.flush(); 
     if (out != null) 
      out.close(); 

     BufferedInputStream bis = new BufferedInputStream(new FileInputStream(portName), 512); 
     System.out.println("Connected to device"); 

     while(System.currentTimeMillis() < startTime+1000) { 
      avail = bis.available(); 
      if (!(avail > 0)) { 
       System.out.println("Available: " + avail); 
       continue; 
      } 

      singleByte = (byte) bis.read(); 
      // Do stuff with data  
     } 
     if (bis != null) 
      bis.close();    
    } catch (IOException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
     System.out.println("ERROR"); 
    } 

} 

的錯誤跟蹤:

Connected to device 
java.io.IOException 
    at java.io.FileInputStream.available(Native Method) 
    at java.io.BufferedInputStream.available(Unknown Source) 
    at test.Test.testRecord(Test.java:58) 
    at test.Test.main(Test.java:135) 
ERROR 

我做錯什麼了嗎?如果我註釋掉可用的()調用,那麼除了它每隔50次運行一次大約阻塞read()的問題之外,它完全可以工作。我也嘗試通過InputStreamReader(作爲數據是ASCII)並使用BufferedReader的ready()方法實現讀取器作爲BufferedReader,但始終返回false。

編輯:我正在尋找替代方法來檢查在讀取之前是否有數據可用,其中大部分涉及處理阻塞的read()調用。我有一個外部線程檢查超時,但如果有超時,試圖用thread.interrupt()停止線程仍然不會中斷阻塞read()調用。同樣,從外線關閉InputStream不起作用,因爲呼叫仍然被阻止。我也試過這裏的解決方案https://stackoverflow.com/a/9832633/1020006但是executor.shutdownNow()只是Thread.interrupt()的一個包裝,所以也有同樣的問題。我想避免使用Thread.stop(),因爲它已被棄用。

我能看到的唯一的另一種選擇是使用FileChannel重寫讀取,它們是異步中斷的。

編輯2:我嘗試過使用Thread.stop(),但這也不起作用,正如Peter Lawrey在評論中指出的那樣,這是系統故障的指示性行爲。我設法通過將讀取重構爲一個AsynchronousFileChannel對象來完成所有工作,AsynchronousFileChannel對象從其讀取調用中返回一個Future對象。可以通過get()方法中的超時從Future中獲取數據。然後這會引發一個TimeoutException,它可以被捕獲以關閉該通道。

+0

java.io阻塞API。考慮使用非阻塞的java.nio – ponomandr 2014-09-06 16:07:14

+0

你沒有做錯任何事情,這可能是一個實現錯誤。 – 2014-09-06 16:10:48

+0

//用數據做東西 - 你在那裏做什麼?確保該代碼中的某個位置沒有關閉該流。 – BatScream 2014-09-06 16:35:49

回答

0

閱讀我嘗試過的不同方法的編輯,但我設法通過將讀取重構爲一個AsynchronousFileChannel對象,從讀取調用中返回一個Future對象,從而實現了所有工作。可以通過get()方法中的超時從Future中獲取數據。然後這會引發一個TimeoutException,它可以被捕獲以關閉該通道。