2014-09-06 1 views
1

У меня есть простое тестовое приложение, которое подключается к USB-устройству (в виде локального файла), передает стартовый символ передачи, а затем считывает ввод с устройства. Все это работает нормально, но редко он блокируется при вызове read(). Чтобы предотвратить это, я попытался проверить, есть ли хотя бы 1 доступный байт, прежде чем продолжить операцию read(). Однако, когда я запускаю это, я получаю IOException из вызова available().Доступные байты Java для BufferedInputStream не работают

Мой код:

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 запусков. Я также попытался реализовать читателя как BufferedReader над InputStreamReader (поскольку данные ASCII) и использовать метод ready() BufferedReader, но всегда возвращает false.

EDIT: Я ищу альтернативы проверке наличия данных перед чтением, большинство из которых связано с обработкой блокирующего вызова read(). У меня есть внешний поток, проверяющий тайм-аут, но если есть тайм-аут, попытка остановить поток с помощью thread.interrupt() все равно не прервет вызов блокировки read(). Точно так же закрытие InputStream из внешнего потока не работает, так как вызов по-прежнему заблокирован. Я также попробовал решение здесь https://stackoverflow.com/a/9832633/1020006, но executor.shutdownNow() - это просто оболочка для Thread.interrupt() и поэтому имеет ту же проблему. Я хочу избежать использования Thread.stop(), поскольку он устарел.

Единственный другой выбор, который я вижу, это переписать чтение с помощью FileChannel, которые асинхронно прерываются.

EDIT 2: Я попытался использовать Thread.stop(), но это также не сработало, как отметил Питер Лоури в комментариях, это показательное поведение системной ошибки. Мне удалось заставить все это работать, рефакторинг чтения в объект AsynchronousFileChannel, который возвращает объект Future из его прочитанного вызова. Данные можно получить из Будущего с тайм-аутом в методе get(). Затем это генерирует исключение TimeoutException, которое можно поймать, чтобы закрыть канал.

+0

java.io блокирует API. Вместо этого используйте java.nio, который не блокирует – ponomandr

+0

. Вы ничего не делаете неправильно, это может быть ошибка реализации. –

+0

// Делайте материал с данными - что вы там делаете? Убедитесь, что поток не закрыт где-то в этом коде. – BatScream

ответ

0

Прочитайте изменения для различных методов, которые я пробовал, но мне удалось заставить все это работать, рефакторинг чтения в объект AsynchronousFileChannel, который возвращает объект Future из его прочитанного вызова. Данные можно получить из Будущего с тайм-аутом в методе get(). Затем это генерирует исключение TimeoutException, которое можно поймать, чтобы закрыть канал.

Смежные вопросы