VADCP_WorkHorse Commands and Output Data Format 数据解析GPS

   在某个夏日炎炎的午后,正在摸鱼的小邓接到行任务需要从某个adcp设备的记录PD0文件中解析对应的gps数据,如下:

使用vscode打开对应的pd0文件(使用插件HEx editor打开此二进制文件)如下找到gps对应的数据块:

相关的解析代码如下: 

@Getter
public class WHM {
    //java
    private byte[] array;
    private List<Integer> lists = new ArrayList<>();
    private int _fileLength = -1;
    private StringBuffer errorMessage = new StringBuffer();

    public List<WHMData> getWHMData(String fileName) {
        List<WHMData> list = new ArrayList<>();
        if (!readData(fileName)) {
            return null;
        }
        int num = _fileLength = lists.size();
        int num2 = 0;
        if (num == 0) {
            errorMessage.append(", 没有数据");
            return null;
        }
        while (num2 < num) {
            //pd0文件的记录开始为7F(lsb) 和7F (msb) 对应的10进制为127
            if (this.lists.get(num2) == 127 && this.lists.get(num2 + 1) == 127) {
                //num2 + 2 后面的2个字节描述的是pd0记录的总大小
                int num3 = BitConverterUtil.ToUInt16(this.array, num2 + 2);
                //由于可变leader和固定leader的长度加起来超过120 没有超过的就是不合法的
                if (num3 > 120) {
                    //检查数据是否在合法范围中
                    if (verifyEnsembleData(num2, num3)) {
                        int num4 = num2;
                        //类别的种类
                        int num5 = this.array[num2 + 5];
                        int[] array = new int[num5];
                        for (int i = 0; i < num5; i++) {
                            //每个类别的数据长度
                            array[i] = BitConverterUtil.ToUInt16(this.array, num2 + 6 + i * 2);
                        }
                        //类别的起始位置
                        num2 = num4 + array[0];
                        //固定leader的开头位置 00 00
                        if (this.lists.get(num2) == 0 && this.lists.get(num2 + 1) == 0) {
                            WHMData wHMData = new WHMData();
                            for (int j = 1; j < num5; j++) {
                                num2 = num4 + array[j];
                                //gps数据你开始位置0x2220 对应的10进制为 34 和 32
                                if (this.lists.get(num2) == 34 && this.lists.get(num2 + 1) == 32) {
                                    //最后的类别的长度用总长-起点位置
                                    int charLength = j + 1 >= num5 ? num3 - num2 : num4 + array[j + 1] - num2;
                                    String asciiStringFromList = getAsciiStringFromList(lists, num2, charLength);
                                    System.out.println(asciiStringFromList);
                                }
                            }
                            list.add(wHMData);
                        } else {
                            errorMessage.append(", 数据格式错误");
                        }
                        num2 = num4 + num3 + 2;
                    } else {
                        num2++;

                    }
                } else {
                    num2++;
                }
            } else {
                num2++;
            }
        }
        return list;

    }

    public static String getAsciiStringFromList(List<Integer> list, int startIndex, int x) {
        // 确保起始索引和数量在列表范围内
        if (startIndex < 0 || startIndex >= list.size() || startIndex + x > list.size()) {
            throw new IllegalArgumentException("起始索引或数量超出列表范围");
        }
        StringBuilder result = new StringBuilder();
        // 从指定位置开始,取出x个元素
        for (int i = startIndex; i < startIndex + x; i++) {
            // 将整数转换为ASCII字符并追加到结果字符串
            result.append((char) list.get(i).intValue());
        }
        return result.toString();
    }


    public static void main(String[] args) {
        WHM whm = new WHM();
        List<WHMData> whmData = whm.getWHMData("E:\\temp\\002GPSDown.PD0");
    }


    private boolean readData(String fileName) {
        File file = new File(fileName);
        try (FileInputStream fis = new FileInputStream(file)) {
            // 获取文件大小
            long fileSize = file.length();
            // 根据文件大小创建byte数组
            array = new byte[(int) fileSize];
            // 读取文件内容到byte数组
            int bytesRead = fis.read(array);
            // 检查是否成功读取了所有字节
            if (bytesRead != fileSize) {
                // 如果读取的字节数不等于文件大小,可能发生了错误(尽管这里可能是EOF,但为简单起见,我们处理为错误)
                errorMessage.append(", 无法完全读取文件");
                return false;
            }
            // 转换byte数组超过范围的值
            for (int i = 0; i < array.length; i++) {
                //java中的byte是-128 到127之间 将其转为正数存在list中
                lists.add(i, array[i] & 0xFF);
            }
            // 如果一切正常,返回true
            return true;
        } catch (Exception e) {
            errorMessage.append(", 无法打开文件 " + e);
            return false;
        }
    }

    private boolean verifyEnsembleData(int startPos, int ensembleLength) {
        //2723   startPos 716  ensembleLength 734
        long num = 0L;
        for (int i = 0; i < ensembleLength; i++) {
            num += this.lists.get(startPos + i);
        }
        num %= 65536;
        long num2 = BitConverterUtil.ToUInt16(array, startPos + ensembleLength);
        return num == num2;
    }


}

结果如下:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

焱童鞋

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值