在 python 中读取 bin 文件 - 学习什么

Reading bin files in python - what to learn

提问人:Jonathanthesailor 提问时间:11/3/2023 更新时间:11/3/2023 访问量:71

问:

我有一个由科学设备创建的 .bin 文件,以及一个描述数据结构的 .h 文件(超过 1000 行)。

我想将此文件读入python以进行进一步分析。我在python方面有一定的经验,但是完全被这个问题淹没了。我真的没有一个确切的问题,但我想知道,做到这一点的途径是什么,我必须学习什么?在这一点上,我什至不确定该谷歌什么。

如果我没有找到更好的主意,我将不得不学习 c,编写加载 .bin 文件的 c 代码,然后将数据存储在 .csv 文件中,然后我可以在 python 中读取该文件。

到目前为止我尝试过的(感谢 chatgpt):我使用我的 .h 文件创建了一个带有 ctypesgen 的模块,并将其导入到我的 python 文件中。现在我不确定如何继续。这是数据的基本结构。一般来说,它应该包含 3000 个数据包,每个数据包包含测量数据以及其他数据。

PACK(struct xStatusType
{
  struct priv_timeval           TimeOfDayMaster;
  struct IWG1Type               IWG1Data;
  uint8_t                       bPumpDataValid;
  struct xPumpStatusType        xPumpStatus;
  uint8_t                       bDetDataValid; 
  struct xDetStatusType         xDetStatus;
  struct NTPStatType            NTPStatus;             
  uint16_t                      InstrumentAction;       
});
python c 解析 ctypes

评论

3赞 Barmar 11/3/2023
看一下模块。它允许您定义用于处理结构化二进制数据的格式字符串。struct
1赞 Barmar 11/3/2023
另请参阅 cstruct
0赞 jwal 11/3/2023
unpack_from到一个列表中,在处理文件时按大小索引偏移量。

答:

1赞 Mark Tolonen 11/3/2023 #1

没有给出完整的结构定义,但这应该让你了解如何读取和写入固定结构数据:ctypes

import ctypes as ct

# A simple structure
class A(ct.Structure):
    _pack_ = 1  # to prevent padding bytes for misaligned data
    _fields_ = (('a', ct.c_int32),  # size 4
                ('b', ct.c_uint8),  # size 1
                ('c', ct.c_uint16)) # size 2 (total 7)
    def __repr__(self):
        return f'A(a={self.a}, b={self.b}, c={self.c})'

# A structure with nested structure
class B(ct.Structure):
    _pack_ = 1
    _fields_ = (('a', A),           # size 7
                ('b', ct.c_uint8))  # size 1 (total 8)
    def __repr__(self):
        return f'B(a={self.a}, b={self.b})'

with open('out.bin', 'wb') as fout:
    # write a couple of records
    a = A(1,2,3)
    b = B(a, 4)
    to_write = bytes(b)
    print(to_write)
    fout.write(to_write)
    a = A(5,6,7)
    b = B(a, 8)
    to_write = bytes(b)
    print(to_write)
    fout.write(to_write)

print()
with open('out.bin', 'rb') as fin:
    while data := fin.read(ct.sizeof(B)):  # while breaks if no data read
        print(data)
        b = B.from_buffer_copy(data)  # copy byte data into structure
        print(b)

输出:

b'\x01\x00\x00\x00\x02\x03\x00\x04'
b'\x05\x00\x00\x00\x06\x07\x00\x08'

b'\x01\x00\x00\x00\x02\x03\x00\x04'
B(a=A(a=1, b=2, c=3), b=4)
b'\x05\x00\x00\x00\x06\x07\x00\x08'
B(a=A(a=5, b=6, c=7), b=8)