【发布时间】:2017-04-21 18:11:10
【问题描述】:
我有一个连接到 USB 设备的程序,USB 设备是一种消费产品,使用他们的软件和 PuttY 可以正常工作,这是一个相当简单的使用字符串的串行通信。 (根据他们的文档)。
我的一些代码有问题,特别是在尝试使用 读取字符串而不只是显示它时 我会尽量弄清楚发生了什么:
- 首先,软件会扫描可用的 COM 端口(有效),然后 填充列表
- 其次,用户选择一个 COM 端口并连接到它(这可行),打开 COM 端口,并初始化一个侦听器和一个 I/O 流
- 第三个事件监听器不断更新用户可见的日志与正在接收的数据(这工作正常 好)
但是!有一个开始执行测试的按钮,该测试启用布尔“testinprogress”,使侦听器对可用数据执行不同的任务,以显示正在读取的内容。
这里是事件监听器的代码:
@Override
public void serialEvent(SerialPortEvent evt) {
BufferedReader reader = null;
if (evt.getEventType() == SerialPortEvent.DATA_AVAILABLE)
{
if (testProgress == true)
{
try
{
reader = new BufferedReader(new InputStreamReader(input));
TemperatureParser parser = new TemperatureParser();
TemperatureReading reading;
output.flush();
reading = parser.parse(reader.readLine());
readings.add(reading);
textLog.appendText(reader.readLine() + "\n");
}
catch (Exception e)
{
statusLabel.setText("@serialEvent.IF Failed to read data. (" + e.toString() + ")");
System.out.println("@SerialEvent.IF Failed to read data. (" + e.toString() + ")");
}
}
else
{
try
{
reader = new BufferedReader(new InputStreamReader(input));
fullLine = reader.readLine();
textLog.appendText(fullLine + "\n");
}
catch (Exception e)
{
statusLabel.setText("@serialEvent.ELSE Failed to read data. (" + e.toString() + ")");
System.out.println("@SerialEvent.ELSE Failed to read data. (" + e.toString() + ")");
}
}
}
}
现在,问题来了,如果我注释掉以下几行,读取然后显示的东西可以正常工作:
reading = parser.parse(reader.readLine());
readings.add(reading);
这两行与为该项目创建的特殊类有关(感谢 James_D):
//SPECIAL CLASSES NEEDED
public class TemperatureReading {
private final double[] values;
private final LocalDateTime timeStamp;
public TemperatureReading(LocalDateTime timeStamp, double... values) {
this.timeStamp = timeStamp;
this.values = new double[values.length];
System.arraycopy(values, 0, this.values, 0, values.length);
}
public TemperatureReading(double... values){
this(LocalDateTime.now(), values);
}
public double getValue(int channel) {
return values[channel];
}
public int getNumberOfChannels() {
return values.length;
}
public LocalDateTime getTimestamp(){
return timeStamp;
}
public boolean noneExceed(double max) {
return DoubleStream.of(values).allMatch(v -> v <= max);
}
}
public class TemperatureParser {
public TemperatureReading parse (String text) {
return new TemperatureReading(Stream.of(text.split(SPLIT)).mapToDouble(Double::parseDouble).toArray());
}
}
最后,当这些行没有被注释掉时我得到的错误:
OLD ERROR MESSAGES. SEE EDIT
另一个可能与此相关或无关的注意事项是,有时缓冲区读取器不会读取整行,这是我得到的一些输出(这些行被注释掉并且没有错误)
Setting testInProgress to true
24.552 24.505 24.515 24.413
24.457 24.435 24.354 24.433 24.510 24.553 24.506 24.515 24.413
24.458 24.435 24.355 24.433 24.511 24.554 24.507 24.515 24.413
24.458 24.436 24.355 24.433 24.511 24.554 24.507 24.515 24.413
Test stopped by user!
OK
现在您看到,在 testInProgress 设置为 true 后,第一行是 INCOMPLETE(应该是 9 个读数)。我只得到了上一行的部分后半部分,我不知道这是否可能是原因,但即便如此,它们仍然应该能够被解析。
编辑
我修改代码如下:
public class TemperatureParser {
public TemperatureReading parse (String text) {
System.out.println("String received: " + text);
if (text != null && text.length() > 0)
{
return new TemperatureReading(Stream.of(text.split(SPLIT)).mapToDouble(Double::parseDouble).toArray());
}
else
{
System.out.println("Null reading");
return null;
}
}
}
这至少让我知道解析器正在获取完整的字符串行并且它正在工作。还对事件监听器进行了如下修改:(添加了对 72 个字符的检查,即 9 个读数)
if (testProgress == true)
{
try
{
reader = new BufferedReader(new InputStreamReader(input));
fullLine = reader.readLine();
if (fullLine.length() == 72)
{
textLog.appendText(fullLine + "\n");
reading = parser.parse(fullLine);
readings.add(reading);
}
}
catch (Exception e)
{
statusLabel.setText("@serialEvent.IF Failed to read data. (" + e.toString() + ")");
System.out.println("@SerialEvent.IF Failed to read data. (" + e.toString() + ")");
}
有了这个新代码,我得到的错误更少,所以我认为我在正确的轨道上:
testProgress is True
String received: 25.360 25.371 25.254 25.342 25.545 25.609 25.501 25.527 25.444
Exception in thread "Thread-4" java.lang.IllegalStateException: Not on FX application thread; currentThread = Thread-4
@SerialEvent.IF Failed to read data. (java.lang.NumberFormatException: empty String)
at com.sun.javafx.tk.Toolkit.checkFxUserThread(Toolkit.java:236)
at com.sun.javafx.tk.quantum.QuantumToolkit.checkFxUserThread(QuantumToolkit.java:423)
at javafx.scene.Parent$2.onProposedChange(Parent.java:367)
at com.sun.javafx.collections.VetoableListDecorator.setAll(VetoableListDecorator.java:113)
at com.sun.javafx.collections.VetoableListDecorator.setAll(VetoableListDecorator.java:108)
at com.sun.javafx.scene.control.skin.LabeledSkinBase.updateChildren(LabeledSkinBase.java:575)
at com.sun.javafx.scene.control.skin.LabeledSkinBase.handleControlPropertyChanged(LabeledSkinBase.java:204)
at com.sun.javafx.scene.control.skin.LabelSkin.handleControlPropertyChanged(LabelSkin.java:49)
at com.sun.javafx.scene.control.skin.BehaviorSkinBase.lambda$registerChangeListener$61(BehaviorSkinBase.java:197)
at com.sun.javafx.scene.control.MultiplePropertyChangeListenerHandler$1.changed(MultiplePropertyChangeListenerHandler.java:55)
at javafx.beans.value.WeakChangeListener.changed(WeakChangeListener.java:89)
at com.sun.javafx.binding.ExpressionHelper$SingleChange.fireValueChangedEvent(ExpressionHelper.java:182)
at com.sun.javafx.binding.ExpressionHelper.fireValueChangedEvent(ExpressionHelper.java:81)
at javafx.beans.property.StringPropertyBase.fireValueChangedEvent(StringPropertyBase.java:103)
at javafx.beans.property.StringPropertyBase.markInvalid(StringPropertyBase.java:110)
at javafx.beans.property.StringPropertyBase.set(StringPropertyBase.java:144)
at javafx.beans.property.StringPropertyBase.set(StringPropertyBase.java:49)
at javafx.beans.property.StringProperty.setValue(StringProperty.java:65)
at javafx.scene.control.Labeled.setText(Labeled.java:145)
at at.qcresponsetime.FXMLDocumentController.serialEvent(FXMLDocumentController.java:602)
at gnu.io.RXTXPort.sendEvent(RXTXPort.java:772)
at gnu.io.RXTXPort.eventLoop(Native Method)
at gnu.io.RXTXPort$MonitorThread.run(RXTXPort.java:1641)
String received: 25.362 25.371 25.255 25.346 25.547 25.608 25.498 25.527 25.446
@SerialEvent.IF Failed to read data. (java.lang.NumberFormatException: empty String)
String received: 25.363 25.371 25.256 25.350 25.548 25.607 25.495 25.526 25.448
@SerialEvent.IF Failed to read data. (java.lang.NumberFormatException: empty String)
String received: 25.365 25.371 25.257 25.355 25.550 25.607 25.493 25.526 25.450
@SerialEvent.IF Failed to read data. (java.lang.NumberFormatException: empty String)
String received: 25.365 25.371 25.258 25.355 25.550 25.607 25.493 25.526 25.450
@SerialEvent.IF Failed to read data. (java.lang.NumberFormatException: empty String)
String received: 25.365 25.372 25.258 25.355 25.550 25.607 25.493 25.527 25.450
@SerialEvent.IF Failed to read data. (java.lang.NumberFormatException: empty String)
String received: 25.365 25.372 25.258 25.355 25.550 25.607 25.494 25.527 25.450
@SerialEvent.IF Failed to read data. (java.lang.NumberFormatException: empty String)
testProgress is False
Stop Button pressed!
【问题讨论】: