java serial read() 正在无限期地等待 - 如何打破它?
java serial read() is waiting indefinitely - how to break it?
我有一个串行设备连接到我的 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 秒内没有数据?
谢谢,
在这种情况下你的假设是正确的。 BufferedReader
的 readLine()
方法有一个内部的 while-loop
,它将从底层输入流中检索所有字节,并且只有在到达的字符是 \n
或 [= 时才会中断18=].
可以这样想:
while(lastChar != '\n' || lastChar != '\r')
{
//read from stream
}
但是一旦进入方法就不会return。唯一的例外是这两个特殊字符的出现,或者如果 InputStream 关闭(在这种情况下 null
ist returned)。
诀窍是在从 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
which returns true
if there are something to read:
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
}
}
}
您可以使用 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?
}
我有一个串行设备连接到我的 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 秒内没有数据?
谢谢,
在这种情况下你的假设是正确的。 BufferedReader
的 readLine()
方法有一个内部的 while-loop
,它将从底层输入流中检索所有字节,并且只有在到达的字符是 \n
或 [= 时才会中断18=].
可以这样想:
while(lastChar != '\n' || lastChar != '\r')
{
//read from stream
}
但是一旦进入方法就不会return。唯一的例外是这两个特殊字符的出现,或者如果 InputStream 关闭(在这种情况下 null
ist returned)。
诀窍是在从 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
which returns true
if there are something to read:
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
}
}
}
您可以使用 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?
}