2

我想读取一个包含大量二进制数据的文件。我想将此二进制数据转换为 ASCII 格式。在开始时,我想读取 2 个字节,表示消息的大小,消息在大小之前。阅读整条消息后,再次重复相同的操作,2 个字节的消息大小,然后是实际消息。

打印输入数据的代码-

with open("abc.dat", "rb") as f:
byte = f.read(1)
i = 0 
while byte:
    i += 1
    print byte+' ',
    byte = f.read(1)
    if i is 80:
        sys.exit()

输入数据(80 字节)-

  O  T  C  _  A  _  R  C  V  R                                                            P  V  �  W          �  w              /  �              �  �  '            �  �  &  �  

编辑1-。> 使用 hexdump -n200 otc_a_primary_1003_0600.dat 命令输出 -

0000000 4f03 4354 415f 525f 5643 0052 0000 0000
0000010 0000 0000 0000 0000 0000 0000 0000 0000
0000020 0000 0000 0000 0000 5650 57f2 0000 0000
0000030 77d1 0002 0000 0000 902f 0004 0000 0000
0000040 a2bd 1027 0000 0000 d695 e826 2e0b 3e11
0000050 aa55 0300 f332 0000 0046 0000 0000 0000
0000060 5650 57f2 0000 0000 22f8 0a6c 0000 0000
0000070 3030 3030 3730 3435 5135 0000 0000 0100
0000080 bdb4 0100 3000 5131 5a45 1420 077a 9c11
0000090 3591 1416 077a 9c11 dc8d 00c0 0000 0000
00000a0 0000 4300 5241 2020 7f0c 0700 ed0d 0700
00000b0 2052 2020 2030 aa55 0300 f332 0000 0046
00000c0 0000 0000 0000 5650                    
00000c8

我正在使用 python 的struct模块。python版本-python 2.7.6

程序代码——

import struct

msg_len = struct.unpack('h', f.read(2))[0]
msg_data = struct.unpack_from('s', f.read(msg_len))[0]
print msg_data

但我看不到实际消息,控制台上只打印单个字符。如何以适当的方式读取此类二进制文件的消息?

4

3 回答 3

2

这取决于您的两个字节长度如何存储在数据中,例如,如果文件的前两个字节(作为十六进制)是00 01这是否意味着后面的消息是1字节长或256字节长?这被称为大端或小端格式。尝试以下两种方法,一个应该给出更有意义的结果,它旨在读取消息长度块中的数据:

大端格式

import struct

with open('test.bin', 'rb') as f_input:
    length =  f_input.read(2)

    while len(length) == 2:
        print f_input.read(struct.unpack(">H", length)[0])
        length =  f_input.read(2)

小端格式

import struct

with open('test.bin', 'rb') as f_input:
    length =  f_input.read(2)

    while len(length) == 2:
        print f_input.read(struct.unpack("<H", length)[0])
        length =  f_input.read(2)

实际数据需要进一步处理。告诉 struct将H2 个字节作为 an 来处理unsigned short(即该值永远不能被认为是负数)​​。

其他需要考虑的是,有时长度包括自身,因此长度为 2 可能意味着一条空消息。

于 2016-10-12T09:44:06.853 回答
1

尝试:

import struct

with open('abc.dat', 'rb') as f:
    while True:
        try:
            msg_len = struct.unpack('h', f.read(2))[0] # assume native byte order
            msg_data = f.read(msg_len) # just read 'msg_len' bytes
            print repr(msg_data)
        except:
            # something wrong or reach EOF
            break
于 2016-10-12T10:37:28.217 回答
1

来自文档

对于 's' 格式字符,计数被解释为字符串的大小,而不是像其他格式字符那样的重复计数;例如,'10s' 表示单个 10 字节字符串,而 '10c' 表示 10 个字符。如果未给出计数,则默认为 1。对于打包,字符串将被截断或用空字节填充以使其适合。对于解包,生成的字符串始终具有完全指定的字节数。作为一种特殊情况,'0s' 表示单个空字符串(而 '0c' 表示 0 个字符)。

's'应修改为str(msg_len)+'s'. msg_len提前检查是否明智似乎是个好主意。

于 2016-10-12T09:03:46.637 回答