什么是在Java中分割和分析一系列数据点的最有效方法

时间:2017-04-19 17:08:32

标签: java javafx

我的项目陷入僵局,我正在试图弄清楚如何做到这一点,但当我找到一个新的解决方案时,它似乎比我想象的更成问题。我很感激帮助提高效率:

  • 我有一个USB设备,每1/3秒输出一次:

    00.000  00.000  00.000  00.000  00.000  00.000  00.000  00.000(Char 13)(Char 10)
    

它们是9个不同通道的温度值(它们不是零),最后是Char 13和Char 10(ASCII)。每个值都被2个空格分割。

我想做以下事情:

  • 每1/3秒阅读一次
  • 使用2个空格(变量SPLIT = " +"
  • 拆分字符串
  • 将每个阅读内容存储到chx[]数组
  • 制作一个新的数组time[],以1/3秒为增量递增
  • 冲洗重复。

因此,在整个过程结束时,我想要有9个Channel[]数组,每个数组都有x值,另外还有第10个Time[]数组,其中包含x值。

此循环需要继续运行,直到9个通道中的一个超过一定温度。然后,我将分析每个通道的数据,并查看它升温到该温度所需的时间(时间)(主要是检查响应时间)。

以下是我发现的主要问题:

  • 我想在if循环中执行此操作,但是我似乎无法想出一种方法来说明这一点,它将是以下内容:

    if( /* HOW DO I CONVERT ALL 9 VALUES TO DOUBLES TO CHECK? */ <= finalTemp)
    {
    }
    
  • 我的推理有效吗? (每个通道的数组和时间数组?) 如果是这样的话,我想我会做一个for循环分裂,就像这样:

    String[] fullReadings = readData().split(SPLIT);  
    Double[] channel0 = null;  
    Double[] channel1 = null;  
    Double[] channel2 = null;  
    Double[] channel3 = null;  
    Double[] channel4 = null;  
    Double[] channel5 = null;  
    Double[] channel6 = null;  
    Double[] channel7 = null;  
    Double[] time = null;  
    
    for (int i=0; i<8 ; i++){
    fullReadings = readData().split(SPLIT);
    
    /* DO I JUST SAY */ channeli = Double.parseDouble(fullReadings[i]); //??
    
    }
    

我感谢你的帮助,我希望我能说清楚。

修改 谢谢你的帮助到目前为止 截至目前我已经添加了@James_D建议的类,我正在尝试他的方法,我有以下扫描程序代码,因为我无法像他建议的那样逐字地声明:

try
        {
            BufferedReader reader = new BufferedReader(new InputStreamReader(input));
                    Scanner inputScanner = new Scanner(input);
                    TemperatureParser parser = new TemperatureParser();
                    inputScanner.useDelimiter("\r\n");
                    do
                    {
                        reading = parser.parse(inputScanner.next());
                        System.out.println(reading);
                        readings.add(reading);
                    } while (testProgress == true);
                    inputScanner.close();
        }
        catch (Exception e)
                {
                statusLabel.setText("Failed to read data. (" + e.toString() + ")");
                System.out.println("Failed to read data. (" + e.toString() + ")");
                }
    }

方法之外是这些声明:

public List<TemperatureReading> readings = new ArrayList<>();
public TemperatureReading reading;

由于我没有温度(物理上),我只是添加了一个开始/停止按钮(布尔testProgress)

另外,有以下代码输出空白数组吗?

    @FXML
    private void doStopTest(ActionEvent event) {
        setTestInProgress(false);
        writeData(BURSTOFF);
        System.out.println("Stop Button pressed!");
        textLog.appendText("Test stopped by user! \n");
        System.out.println(readings);
        statusLabel.setText("Stopped by User!");
}

新编辑

感谢James_D到目前为止你的所有帮助,我真的很感激。这是我的eventlistener代码,因为到目前为止它一直在工作我决定将它与你建议的一些代码合并:基本上,如果有一个正在进行的测试它会记录,如果没有正在进行的测试它只输出到一个日志文本框

public void serialEvent(SerialPortEvent evt) {          
        if (evt.getEventType() == SerialPortEvent.DATA_AVAILABLE)
        {
            if (testProgress == false)
            {
            try
            {
                BufferedReader reader = new BufferedReader(new InputStreamReader(input));

                    fullLine = reader.readLine();

                    //System.out.println(fullLine);
                    textLog.appendText(fullLine + "\n");
                    output.flush();
            }

            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
                {
                    BufferedReader reader = new BufferedReader(new InputStreamReader(input));
                    TemperatureParser parser = new TemperatureParser();
                    reading = parser.parse(reader.readLine());
                    readings.add(reading);
                    fullLine = reader.readLine();
                    textLog.appendText(fullLine + "\n");
                    output.flush();
                }
                catch (Exception e)
                {
                statusLabel.setText("@serialEvent.ELSE Failed to read data. (" + e.toString() + ")");
                System.out.println("@SerialEvent.ELSE Failed to read data. (" + e.toString() + ")");

                }

            }
        }


}

当我点击停止按钮时(一旦达到MAX温度,这将是自动的)我有以下代码:

private void doStopTest(ActionEvent event) {
    writeData(BURSTOFF);
    System.out.println("Stop Button pressed!");
    textLog.appendText("Test stopped by user! \n");
    System.out.println(readings);
    statusLabel.setText("Stopped by User!");
    setTestInProgress(false);

    for (int t = 0; t < readings.size(); t++)
    {
        System.out.println("Time: " + readings.get(t).getTimestamp() + " CH1: " + readings.get(t).getValue(0) + " CH2: " + readings.get(t).getValue(1) + " CH3: " + readings.get(t).getValue(2) + " CH4: " + readings.get(t).getValue(3) + " CH5: " + readings.get(t).getValue(4) + " CH6: " + readings.get(t).getValue(5) + " CH7: " + readings.get(t).getValue(6) + " CH8: " + readings.get(t).getValue(7) + " CH9: " + readings.get(t).getValue(8));
    }
}

当我运行程序时,我得到以下输出:

testProgress is True
Exception in thread "Thread-4" java.lang.IllegalStateException: Not on FX application thread; currentThread = Thread-4
@SerialEvent.ELSE Failed to read data. (java.io.IOException: Underlying input stream returned zero bytes)
    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:583)
    at gnu.io.RXTXPort.sendEvent(RXTXPort.java:772)
    at gnu.io.RXTXPort.eventLoop(Native Method)
    at gnu.io.RXTXPort$MonitorThread.run(RXTXPort.java:1641)
@SerialEvent.ELSE Failed to read data. (java.io.IOException: Underlying input stream returned zero bytes)
@SerialEvent.ELSE Failed to read data. (java.io.IOException: Underlying input stream returned zero bytes)
@SerialEvent.ELSE Failed to read data. (java.io.IOException: Underlying input stream returned zero bytes)
@SerialEvent.ELSE Failed to read data. (java.io.IOException: Underlying input stream returned zero bytes)
@SerialEvent.ELSE Failed to read data. (java.io.IOException: Underlying input stream returned zero bytes)
@SerialEvent.ELSE Failed to read data. (java.io.IOException: Underlying input stream returned zero bytes)
@SerialEvent.ELSE Failed to read data. (java.io.IOException: Underlying input stream returned zero bytes)
@SerialEvent.ELSE Failed to read data. (java.io.IOException: Underlying input stream returned zero bytes)
@SerialEvent.ELSE Failed to read data. (java.io.IOException: Underlying input stream returned zero bytes)
@SerialEvent.ELSE Failed to read data. (java.io.IOException: Underlying input stream returned zero bytes)
@SerialEvent.ELSE Failed to read data. (java.io.IOException: Underlying input stream returned zero bytes)
@SerialEvent.ELSE Failed to read data. (java.io.IOException: Underlying input stream returned zero bytes)
@SerialEvent.ELSE Failed to read data. (java.io.IOException: Underlying input stream returned zero bytes)
@SerialEvent.ELSE Failed to read data. (java.io.IOException: Underlying input stream returned zero bytes)
Stop Button pressed!
[at.qcresponsetime.FXMLDocumentController$TemperatureReading@44c159a9, at.qcresponsetime.FXMLDocumentController$TemperatureReading@6fed877b, at.qcresponsetime.FXMLDocumentController$TemperatureReading@2529a9d6, at.qcresponsetime.FXMLDocumentController$TemperatureReading@efba5c8, at.qcresponsetime.FXMLDocumentController$TemperatureReading@4039a9af, at.qcresponsetime.FXMLDocumentController$TemperatureReading@43ec288c, at.qcresponsetime.FXMLDocumentController$TemperatureReading@2b635e3e, at.qcresponsetime.FXMLDocumentController$TemperatureReading@78e57b7f, at.qcresponsetime.FXMLDocumentController$TemperatureReading@751cc11d, at.qcresponsetime.FXMLDocumentController$TemperatureReading@57962f7a, at.qcresponsetime.FXMLDocumentController$TemperatureReading@66b51918, at.qcresponsetime.FXMLDocumentController$TemperatureReading@3558b832, at.qcresponsetime.FXMLDocumentController$TemperatureReading@26df83ad, at.qcresponsetime.FXMLDocumentController$TemperatureReading@40d485f3, at.qcresponsetime.FXMLDocumentController$TemperatureReading@ee72928]
testProgress is False
Time: 2017-04-20T15:28:19.118 CH1: 24.024 CH2: 23.961 CH3: 23.889 CH4: 24.163 CH5: 24.085 CH6: 24.107 CH7: 24.017 CH8: 24.042 CH9: 24.473
Time: 2017-04-20T15:28:19.428 CH1: 24.044 CH2: 23.989 CH3: 23.916 CH4: 24.188 CH5: 24.112 CH6: 24.144 CH7: 24.05 CH8: 24.07 CH9: 24.476
Time: 2017-04-20T15:28:19.764 CH1: 24.063 CH2: 24.016 CH3: 23.942 CH4: 24.214 CH5: 24.138 CH6: 24.179 CH7: 24.082 CH8: 24.097 CH9: 24.479
Time: 2017-04-20T15:28:20.099 CH1: 24.083 CH2: 24.043 CH3: 23.969 CH4: 24.24 CH5: 24.164 CH6: 24.215 CH7: 24.114 CH8: 24.123 CH9: 24.482
Time: 2017-04-20T15:28:20.418 CH1: 24.102 CH2: 24.043 CH3: 23.996 CH4: 24.24 CH5: 24.191 CH6: 24.215 CH7: 24.114 CH8: 24.151 CH9: 24.485
Time: 2017-04-20T15:28:20.753 CH1: 24.102 CH2: 24.043 CH3: 23.996 CH4: 24.24 CH5: 24.191 CH6: 24.215 CH7: 24.113 CH8: 24.151 CH9: 24.485
Time: 2017-04-20T15:28:21.088 CH1: 24.102 CH2: 24.043 CH3: 23.996 CH4: 24.241 CH5: 24.191 CH6: 24.215 CH7: 24.113 CH8: 24.151 CH9: 24.485
Time: 2017-04-20T15:28:21.408 CH1: 24.103 CH2: 24.043 CH3: 23.996 CH4: 24.241 CH5: 24.191 CH6: 24.215 CH7: 24.113 CH8: 24.151 CH9: 24.485
Time: 2017-04-20T15:28:21.743 CH1: 24.103 CH2: 24.043 CH3: 23.996 CH4: 24.242 CH5: 24.191 CH6: 24.215 CH7: 24.113 CH8: 24.152 CH9: 24.485
Time: 2017-04-20T15:28:22.062 CH1: 24.103 CH2: 24.044 CH3: 23.996 CH4: 24.242 CH5: 24.192 CH6: 24.216 CH7: 24.113 CH8: 24.152 CH9: 24.485
Time: 2017-04-20T15:28:22.398 CH1: 24.103 CH2: 24.044 CH3: 23.996 CH4: 24.243 CH5: 24.192 CH6: 24.216 CH7: 24.113 CH8: 24.152 CH9: 24.485
Time: 2017-04-20T15:28:22.733 CH1: 24.104 CH2: 24.043 CH3: 23.996 CH4: 24.243 CH5: 24.193 CH6: 24.216 CH7: 24.113 CH8: 24.152 CH9: 24.485
Time: 2017-04-20T15:28:23.052 CH1: 24.104 CH2: 24.044 CH3: 23.996 CH4: 24.244 CH5: 24.193 CH6: 24.216 CH7: 24.113 CH8: 24.152 CH9: 24.485
Time: 2017-04-20T15:28:23.387 CH1: 24.103 CH2: 24.043 CH3: 23.996 CH4: 24.244 CH5: 24.193 CH6: 24.216 CH7: 24.113 CH8: 24.152 CH9: 24.485
Time: 2017-04-20T15:28:23.723 CH1: 24.103 CH2: 24.043 CH3: 23.995 CH4: 24.244 CH5: 24.193 CH6: 24.216 CH7: 24.113 CH8: 24.152 CH9: 24.485

所以你可以看到它确实记录了一些数据并准确显示(或者看起来如此),当我点击“开始测试”按钮输出第一行(testprogress为true)时它就是布尔值标记以保持上面的代码记录。当我单击停止按钮时,你会得到停止按钮按下日志,而testprogress是假行,它会禁用输出。

3 个答案:

答案 0 :(得分:0)

将程序分解为函数。

double[] extractSample(String sampleRow);

double maxTemperature(double[] sample);

根据您正在分析的内容,您可以选择捕获一系列样本,例如list.add(sample),或者您可以在开始时捕获开始时间并从开始时减去当前时间是时候加速了。

答案 1 :(得分:0)

  

此循环需要继续运行,直到9个通道中的一个超过一定温度。

根据我从问题中理解的算法,算法。 注意:未检查语法并且有许多假设,例如readData()会严格阻止1/3秒,这可能不是真的。因此,时间戳需要谨慎。也许使用System.nanoTime()是首选。但是,以下答案与问题的语义完全匹配。

final double finalTemp = ...;

// 9 channels
double[] channels = new double[9];

long tick = 0;

boolean done = false;

// assume that final temp will be reached
while (!done) {

    // disregarding the Char(13), Char(10), so fullReadings contains temp in String format
    String[] fullReadings = readData().split(SPLIT); 

    // assume fullReadings.length == 9
    for (int i = 0; i < fullReadings.length; i++) {

        // assume the value can be parsed with no errors
        double temp = Double.parseDouble(reading);

        channels[i] = temp;

        if (temp >= finalTemp) {
            done = true;
        }
    }

    tick++;
}

System.out.printf("Time took: %.3f seconds\n", tick / 3.0);

for (int i = 0; i < channels.length; i++) {
    System.out.printf("Channel %d has temp: %.3f\n", i, channels[i]);
}

答案 2 :(得分:0)

与往常一样,如果您首先定义一些适当的类来表示应用程序中的数据,您的代码会变得更加简单。

例如,我可能会从一个代表一个时间点所有通道的值集的类开始:

import java.time.LocalDateTime ;
import java.util.stream.DoubleStream ;

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)
    }

}

现在您想要一种将字符串映射到TemperatureReading实例的方法:

import java.util.stream.Stream ;

public class TemperatureReadingParser {

    public TemperatureReading parse(String text) {
        return new TemperatureReading(
            Stream.of(text.split("\\s"))
            .mapToDouble(Double::parseDouble)
            .toArray());
    }
}

现在,您继续阅读的代码如下:

List<TemperatureReading> readings = new ArrayList<>();

TemperatureReadingParser parser = new TemperatureReadingParser();
double max = ... ;
Scanner input = ... ;
input.useDelimiter("\r\n");

TemperatureReading reading ;
do {
    reading = parser.parse(input.next());
    readings.add(reading);
} while (reading.noneExceed(max));

input.close();

获得读数列表后,您可以使用

提取特定频道的所有值
int channel = ... ;
double[] channelValues = readings.stream()
    .mapToDouble(reading -> reading.getValue(channel))
    .toArray();

并根据需要进行分析。