【问题标题】:Finding certian byte data from InputStream从 InputStream 中查找特定字节数据
【发布时间】:2017-01-30 07:32:49
【问题描述】:

我有一个导航单元,它以 200 Hz 的频率吐出 3 条消息数组。

我正在使用套接字和输入流来获取数据,并将其传递给名为 socketReader 的可运行类。另一个可运行的类获取变量并进行一些数学运算并将它们转换为字节并串行发送出去。

这个程序一次会运行大约 8 个小时,数据流将是恒定的,除了第三条消息(GPS 数据),它只会在有单条时发送。

            InputStream in = echoSocket.getInputStream();
            DataInputStream dis = new DataInputStream(in);

            OutputStream out = serialPort.getOutputStream();

            (new Thread(new SocketReader(dis))).start();
            (new Thread(new SerialWriter(out))).start();

我遇到的问题是 socketReader 类。所以我知道十六进制的标头,所以我将数据从 DataInputStream 读取到字节缓冲区和 stringBuilder 中,在那里我将数据放入更多子字符串并将它们转换为浮点数。

这确实有效,我在解析 altHold logHold latHold 字符串时遇到了问题(并且被注释掉了)。它们不是 4 个字节(单精度浮点)的数据,而是 8 个字节(双精度浮点)。但我觉得我在这里重新发明轮子。消息中的数据是最不重要的位,我觉得我这样做的方式正在减慢我的程序?它也不是完美的它会运行一段时间退出循环。

目前我只查看其中两条消息,第三条的发送频率不如前两条。我应该使用 DataInputStream 以外的东西吗?

    public static class SocketReader implements Runnable {  

    //Message headers
    final String mes1 = new String("FF5A0600");
    final String mes2 = new String("FF5A0800");
    final String mes3 = new String("FF5A1300");

    //These are the size of each message
    final int Stop1 = 82;
    final int Stop2 = 162;
    final int Stop3 = 150;

    StringBuilder rolHold = new StringBuilder();
    StringBuilder pitHold = new StringBuilder();
    StringBuilder yawHold = new StringBuilder();

    StringBuilder altHold = new StringBuilder();
    StringBuilder latHold = new StringBuilder();
    StringBuilder logHold = new StringBuilder();
    StringBuilder velNHold = new StringBuilder();
    StringBuilder velEHold = new StringBuilder();

    DataInputStream dis;

    public SocketReader( DataInputStream dis ) {
        this.dis = dis;
    }

    public void run() {

        byte[] buffer;

        //dis is a DataInputStream
        while (dis != null){

            buffer = new byte[ 1024 ];

            try {
                dis.readFully(buffer);
            } catch (IOException e1) {
                e1.printStackTrace();
            }

            StringBuilder sb = new StringBuilder();

            for (byte b: buffer){                   
                sb.append(String.format("%02X", b));
            }

            //Finds the first occurrence of the three messages
            //If the index is -1 there is no occurrence
            int index1 = sb.indexOf(mes1);
            int index2 = sb.indexOf(mes2);
            int index3 = sb.indexOf(mes3);


            while (index1 <= sb.lastIndexOf(mes1)  && (index1 != -1) && (index2 != -1) && (index2 != 0)){


                //this if statement deals with the first message
                //There are three sets of data pulled from message 1 {rolValue, pitValue, yawValue}         
                if (index1 < index2 && (index1 != -1)){

                    //reseting the Stringbuilders 
                    rolHold.setLength(0);
                    pitHold.setLength(0);
                    yawHold.setLength(0);

                    //the data is sent little-endian and is appended in reverse order
                    rolHold.append(sb.substring((index1 + 26),(index1 + 28)));
                    rolHold.append(sb.substring((index1 + 24),(index1 + 26)));
                    rolHold.append(sb.substring((index1 + 22),(index1 + 24)));
                    rolHold.append(sb.substring((index1 + 20),(index1 + 22)));
                    Long rol = Long.parseLong(rolHold.toString(), 16);
                    rolValue = Float.intBitsToFloat(rol.intValue());                            

                    pitHold.append(sb.substring((index1 + 34),(index1 + 36)));
                    pitHold.append(sb.substring((index1 + 32),(index1 + 34)));
                    pitHold.append(sb.substring((index1 + 30),(index1 + 32)));
                    pitHold.append(sb.substring((index1 + 28),(index1 + 30)));
                    Long pit = Long.parseLong(pitHold.toString(), 16);
                    pitValue = Float.intBitsToFloat(pit.intValue());        

                    yawHold.append(sb.substring((index1 + 42),(index1 + 44)));
                    yawHold.append(sb.substring((index1 + 40),(index1 + 42)));
                    yawHold.append(sb.substring((index1 + 38),(index1 + 40)));
                    yawHold.append(sb.substring((index1 + 36),(index1 + 38)));
                    Long yaw = Long.parseLong(yawHold.toString(), 16);
                    yawValue = Float.intBitsToFloat(yaw.intValue());


                    //increments the index1 to its next sequence of message 1
                    //-1 is returned if there is not another
                    index1 = sb.indexOf(mes1, (index1 + Stop1));
                }


                //this if statement deals with the second message
                //There are five sets of data pulled from message 2 {velNValue, velEValue, latValue, logValue, altValue}        
                if(index2 < index1 && (index2 != -1) && (index2 != 0)){ 


                    altHold.setLength(0);
                    latHold.setLength(0);   
                    logHold.setLength(0);
                    velNHold.setLength(0);  
                    velEHold.setLength(0);

                            velNHold.append(sb.substring((navIndex + 26),(navIndex + 28)));
                            velNHold.append(sb.substring((navIndex + 24),(navIndex + 26)));
                            velNHold.append(sb.substring((navIndex + 22),(navIndex + 24)));
                            velNHold.append(sb.substring((navIndex + 20),(navIndex + 22)));
                            Long velN = Long.parseLong(velNHold.toString(), 16);
                            velNValue = Float.intBitsToFloat(velN.intValue());



                            velEHold.append(sb.substring((navIndex + 34),(navIndex + 36)));
                            velEHold.append(sb.substring((navIndex + 32),(navIndex + 34)));
                            velEHold.append(sb.substring((navIndex + 30),(navIndex + 32)));
                            velEHold.append(sb.substring((navIndex + 28),(navIndex + 30)));
                            Long velE = Long.parseLong(velEHold.toString(), 16);
                            velEValue = Float.intBitsToFloat(velE.intValue());


    //                      latHold.append(sb.substring((navIndex + 82),(navIndex + 84)));
    //                      latHold.append(sb.substring((navIndex + 80),(navIndex + 82)));
    //                      latHold.append(sb.substring((navIndex + 78),(navIndex + 80)));
    //                      latHold.append(sb.substring((navIndex + 76),(navIndex + 78)));
    //                      latHold.append(sb.substring((navIndex + 74),(navIndex + 76)));
    //                      latHold.append(sb.substring((navIndex + 72),(navIndex + 74)));
    //                      latHold.append(sb.substring((navIndex + 70),(navIndex + 72)));
    //                      latHold.append(sb.substring((navIndex + 68),(navIndex + 70)));
    //                      Long lat = Long.parseLong(logHold.toString(), 16);
    //                      Float latValue = Float.intBitsToFloat(lat.intValue());                      
    //
    //                      logHold.append(sb.substring((navIndex + 98),(navIndex + 100)));
    //                      logHold.append(sb.substring((navIndex + 96),(navIndex + 98)));
    //                      logHold.append(sb.substring((navIndex + 94),(navIndex + 96)));
    //                      logHold.append(sb.substring((navIndex + 92),(navIndex + 94)));
    //                      logHold.append(sb.substring((navIndex + 90),(navIndex + 92)));
    //                      logHold.append(sb.substring((navIndex + 88),(navIndex + 90)));
    //                      logHold.append(sb.substring((navIndex + 86),(navIndex + 88)));
    //                      logHold.append(sb.substring((navIndex + 84),(navIndex + 86)));
    //                      Long log = Long.parseLong(logHold.toString(), 16);
    //                      Float logValue = Float.intBitsToFloat(log.intValue());
    //
    //
    //                      altHold.append(sb.substring((navIndex + 114),(navIndex + 116)));
    //                      altHold.append(sb.substring((navIndex + 112),(navIndex + 114)));
    //                      altHold.append(sb.substring((navIndex + 110),(navIndex + 112)));
    //                      altHold.append(sb.substring((navIndex + 108),(navIndex + 110)));
    //                      altHold.append(sb.substring((navIndex + 106),(navIndex + 108)));
    //                      altHold.append(sb.substring((navIndex + 104),(navIndex + 106)));
    //                      altHold.append(sb.substring((navIndex + 102),(navIndex + 104)));
    //                      altHold.append(sb.substring((navIndex + 100),(navIndex + 102)));
    //                      Long alt = Long.parseLong(altHold.toString(), 16);
    //                      Float altValue = Float.intBitsToFloat(alt.intValue());  



                    //increments the index2 to its next sequence of message 2
                    //-1 is returned if there is not another
                    index2 = sb.indexOf(mes2, (index2 +Stop2));

                }

            }
        }
    }
}

非常感谢您的帮助,或者如果您能指出我正确的方向,那也很棒。如果您需要我提供更多信息,我很乐意提供。

谢谢!

【问题讨论】:

    标签: java sockets byte inputstream datainputstream


    【解决方案1】:

    不建议(恕我直言)使用DataInputStream 读取不是由DataOutputStream 生成的数据。他们使用自己的协议来写入/读取某些数据类型(例如 UTF 字符串)。

    这不是上面代码的问题,因为它只读取带有readFully(1024) 的字节。但是使用这种方法在这里可能会出现问题:它读取完整的缓冲区(最终阻塞),除非连接关闭(通常或通过异常),也就是说,您的消息必须是 1024 字节长。

    此外,代码所做的转换也很难理解。这就是我认为正在做的事情:字节到字符串(十六进制表示),十六进制值顺序的字符串已更改,转换为长整数,转换为浮点数。 我怀疑用字符串做所有的算术是最好的解决方案......

    无论如何,我建议使用自己的方法,给定字节数组和(开始)索引,返回计算出的 float/double(避免重复,更容易理解和测试),例如:

    private static float readFloat(byte[] buffer, int index) {
        // not done in a loop for demonstration 
        int bits =  (buffer[index+0] & 255) 
                 + ((buffer[index+1] & 255) <<  8) 
                 + ((buffer[index+2] & 255) << 16) 
                 + ((buffer[index+3] & 255) << 24);
        return Float.intBitsToFloat(bits);
    }
    

    恕我直言,一个更好的解决方案是使用ByteBuffer 包装或代替byte[]ByteBuffer 可以设置为 little-endian,并具有获取 float 和 double 的方法 (example),并且也是从 Socket 读取的选项

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-01-02
      • 1970-01-01
      • 2014-11-30
      • 2012-02-01
      • 2023-03-30
      • 2018-02-17
      • 1970-01-01
      • 2010-11-01
      相关资源
      最近更新 更多