ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

使用Python,如何从具有多个可变长度记录的二进制数据文件中读取和提取数据?

2019-07-22 02:58:41  阅读:414  来源: 互联网

标签:python gps binary-data


使用Python(3.1或2.6),我试图从GPS接收器生成的二进制数据文件中读取数据.每小时的数据存储在一个单独的文件中,每个文件大约18 MiB.数据文件有多个可变长度记录,但是现在我需要从其中一个记录中提取数据.

我已经有了能够解码头部的程度.我有点说,因为有些数字没有意义,但大多数都没有.花了几天时间(我开始学习使用Python编程),我没有取得进展,所以是时候寻求帮助了.

参考指南为我提供了消息头结构和记录结构.标头长度可变,但通常为28个字节.

Header
Field #  Field Name    Field Type    Desc                 Bytes    Offset
1        Sync          char          Hex 0xAA             1        0
2        Sync          char          Hex 0x44             1        1
3        Sync          char          Hex 0x12             1        2
4        Header Lgth   uchar         Length of header     1        3
5        Message ID    ushort        Message ID of log    2        4
8        Message Lgth  ushort        length of message    2        8
11       Time Status   enum          Quality of GPS time  1        13
12       Week          ushort        GPS week number      2        14
13       Milliseconds  GPSec         Time in ms           4        16


Record
Field #  Data                        Bytes         Format     Units       Offset
1        Header                                                           0
2        Number of SV Observations   4             integer    n/a         H
         *For first SV Observation*  
3        PRN                         4             integer    n/a         H+4
4        SV Azimuth angle            4             float      degrees     H+8
5        SV Elevation angle          4             float      degrees     H+12
6        C/N0                        8             double     db-Hz       H+16
7        Total S4                    8             double     n/a         H+24
...
27       L2 C/N0                     8             double     db-Hz       H+148
28       *For next SV Observation*
         SV Observation is satellite - there could be anywhere from 8 to 13 
         in view.

这是我试图理解标题的代码:

import struct

filename = "100301_110000.nvd"

f = open(filename, "rb")
s = f.read(28)
x, y, z, lgth, msg_id, mtype, port, mlgth, seq, idletime, timestatus, week, millis,    recstatus, reserved, version = struct.unpack("<cccBHcBHHBcHLLHH", s)

print(x, y, z, lgth, msg_id, mtype, port, mlgth, seq, idletime, timestatus, week, millis, recstatus, reserved, version)

它输出:

b'\xaa' b'D' b'\x12' 28 274 b'\x02' 32 1524 0 78 b'\xa0' 1573 126
Header
Field #  Field Name    Field Type    Desc                 Bytes    Offset
1        Sync          char          Hex 0xAA             1        0
2        Sync          char          Hex 0x44             1        1
3        Sync          char          Hex 0x12             1        2
4        Header Lgth   uchar         Length of header     1        3
5        Message ID    ushort        Message ID of log    2        4
8        Message Lgth  ushort        length of message    2        8
11       Time Status   enum          Quality of GPS time  1        13
12       Week          ushort        GPS week number      2        14
13       Milliseconds  GPSec         Time in ms           4        16


Record
Field #  Data                        Bytes         Format     Units       Offset
1        Header                                                           0
2        Number of SV Observations   4             integer    n/a         H
         *For first SV Observation*  
3        PRN                         4             integer    n/a         H+4
4        SV Azimuth angle            4             float      degrees     H+8
5        SV Elevation angle          4             float      degrees     H+12
6        C/N0                        8             double     db-Hz       H+16
7        Total S4                    8             double     n/a         H+24
...
27       L2 C/N0                     8             double     db-Hz       H+148
28       *For next SV Observation*
         SV Observation is satellite - there could be anywhere from 8 to 13 
         in view.

0 10485760 3545 35358

解决方法:

18 MB应该可以很好地适应内存,所以我只需将整个内容放入一个大的字节串中,其中一个打开(文件,’rb’)为f:data = f.read(),然后执行所有操作在片上“解析”以按记录推进记录.它更方便,并且可能比在文件中从此处和那里进行许多小读取更快(尽管它不会影响下面的逻辑,因为在任何一种情况下,“数据中的当前关注点”始终在移动[ [总是转发,因为它发生]]基于一次几个字节的struct-unpack计算的数量,以找到标题和记录的长度).

给定“记录开始”偏移量,您可以通过查看一个字节(“字段四”,从头部开头偏移3,与记录开头相同)来确定其标头的长度,并查看消息ID(下一个字段) ,2个字节)看看它是否是你关心的记录(所以只需要那3个字节的结构解包就足够了).

无论它是否是您想要的记录,您接下来需要计算记录的长度(要么跳过它要么全部得到);为此,您计算实际记录数据的开始(记录的开始加上标题的长度加上记录的下一个字段(标题后面的4个字节)乘以观察的长度(如果我正确读取,则为32个字节) ).

这样你就可以将要给予struct.unpack的子字符串隔离开来(当你最终到达你想要的记录时),或者只是将标题记录的总长度添加到“记录开始”偏移量,以获得偏移量下一条记录的开头.

标签:python,gps,binary-data
来源: https://codeday.me/bug/20190722/1498360.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有