java serial read () ждет бесконечно - как его сломать? - PullRequest
0 голосов
/ 11 июня 2018

К моему PI подключено последовательное устройство, с которого я читаю данные ... все хорошо, но иногда кабель перемещается или последовательное устройство отключается.

, затем

line = r.readLine();

застрять

Я пытаюсь преодолеть эту проблему с помощью:

BufferedReader r = new BufferedReader (newnputStreamReader(p.getInputStream()));     
         try 
            {
                line = r.readLine();
                if (line.length() == 0)
                {
                    logfile.append("problem");
                    logfile.close();
                    System.out.println("Problem");
                    TimeUnit.SECONDS.sleep(5);
                    break;
                }

            }
            catch (IOException e)
            {
                logfile.append(line);
                logfile.close();
            }

, но это ничего не делает (потому что, я думаю, он все еще ждет данных), дажебросить исключение, как я могу заставить его сказать, что у меня есть проблема?может использовать таймер или что-то вроде этого?если нет данных в течение 5 секунд?

Спасибо,

Ответы [ 2 ]

0 голосов
/ 11 июня 2018

Вы можете использовать CompletableFuture для одновременного чтения и использования тайм-аута.

// wrap the readLine into a concurrent call
CompletableFuture<String> lineFuture = CompletableFuture.supplyAsync(() -> r.readLine());
try {
    // do the call, but with a timeout
    String readLine = lineFuture.get(5, TimeUnit.SECONDS);
    // do stuff with the line you read
} catch (TimeoutException e) {
    // plug pulled?
}
0 голосов
/ 11 июня 2018

Ваше предположение в этом случае верно.readLine() метод BufferedReader имеет внутренний while-loop, который извлекает все байты из базового входного потока и прерывается только в том случае, если прибывающий символ равен \n или \r.

Думайте об этом как:

while(lastChar != '\n' || lastChar != '\r')
{
     //read from stream
}

Однако после ввода метод не вернется.Единственными исключениями являются вхождения этих двух специальных символов или закрытие InputStream (в этом случае возвращается null ist).

Хитрость заключается в отсутствии ввода, пока не будет что-то для чтения из InputStream:

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

  boolean awaitInput = true;

  while(awaitInput)
  {
    if(System.in.available() != 0)
    {
      awaitInput = false;
      // read logic
    }
  }
}

Это только одно из многих возможных решений, и я использовал System.in в качестве примера, поскольку он является InputStream, как и любой другой.Но есть также метод с именем BufferedReader#ready, который возвращает true, если есть что прочитать:

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

  BufferedReader br = new BufferedReader( new InputStreamReader(System.in) );

  boolean awaitInput = true;

  while(awaitInput)
  {
    if(br.ready())
    {
      awaitInput = false;
      String line = br.readLine();
      // read logic
    }
  }
}

Наконец, если вы хотите тайм-аут, вы можете легко сделать это самостоятельно, например:

public static void main( String[] args ) throws IOException
{
  BufferedReader br = new BufferedReader( new InputStreamReader(System.in) );
  boolean awaitInput = true;
  long timeout = System.currentTimeMillis() + 5_000;
  //                                          ^^^^^ 5_000ms = 5 sec 

  while(awaitInput && System.currentTimeMillis() < timeout)
  {
    if(br.ready())
    {
      awaitInput = false;
      String line = br.readLine();
      // read logic
    }
  }
}
...