2

我有一个连接到我的 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 秒内没有数据?

谢谢 ,

4

2 回答 2

0

在这种情况下,您的假设是正确的。的readLine()方法BufferedReader有一个 internal ,它将从底层输入流中检索所有字节,并且只有在到达的字符是orwhile-loop时才会中断。\n\r

想一想:

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

但是,一旦进入该方法将不会返回。唯一的例外是出现这两个特殊字符或 InputStream 已关闭(在这种情况下null返回)。

诀窍是在从 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
    }
  }
}
于 2018-06-11T12:57:49.047 回答
0

您可以使用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?
}
于 2018-06-11T13:00:52.263 回答