python之struct模块处理二进制

如果你不相信努力和时光,那么成果就会是第一个选择辜负你的。不要去否定你自己的过去,也不要用你的过去牵扯你现在的努力和对未来的展望。不是因为拥有希望你才去努力,而是去努力了,你才有可能看到希望的光芒。python之struct模块处理二进制,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com,来源:原文

嵌入式开发中,有时需要对二进制流文件进行读写操作,一种方法是将二进制流文件转换为c语言数组形式。

这样可以使用python的struct模块,python的struct模块可以方便的进行字节与二进制之间的相互转换。

1 struct模块常用的几个函数

函数 说明
struct.pack(format, v1, v2, …) 按照给定的格式(fmt),把数据封装成字符串流(包括2进制流)
struct.unpack(format, buffer) 按照给定的格式(fmt)解析字节流,返回解析出来的元组tuple
struct.unpack_from(format, buffer, offset=0) 该函数可以将缓冲区buffer中的内容在按照指定的格式fmt,从偏移量为offset=numb的位置开始进行读取,返回的是一个对应的元组tuple
struct.calcsize(format) 计算给定的格式(fmt)占用多少字节的内存

重要的是清楚格式(fmt)表达的含义,格式包含两个部分:

  1. 数据格式
  2. 数据字节序(大端or小端?)、对齐方式等。

数据格式如下:

Format C Type Python 字节数
x pad byte no value 1
c char string of length 1 1
b signed char integer 1
B unsigned char integer 1
? _Bool bool 1
h short integer 2
H unsigned short integer 2
i int integer 4
I unsigned int integer 4
l long integer 4
L unsigned long integer 4
q long long integer 8
Q unsigned long long integer 8
n ssize_t integer
N size_t integer
e float 2
f float float 4
d double float 8
s char[] string 1
p char[] string 1
P void * integer

字节序、对齐方式如下:

使用特殊字符来控制。

Character Byte order Size and alignment
@ native native 凑够4个字节,等于c语言中的sizeof
= native standard 按原字节数
< little-endian standard 按原字节数
> big-endian standard 按原字节数
! network (= big-endian) standard 按原字节数

细节可以查看官网,这里只展示一个例子。

3 将二进制数据转换成16进制数组

这里提供一个示例,来演示struct的使用。下面代码将二进制数据转换成16进制数组(代码参考2,有修改)。

# bin2hex.py
"""
将二进制数据的bin文件转换成C语言数组的形式并保存为 .c 源文件
"""
import sys, os
import struct

def bin2hex():
    if len(sys.argv) != 2:
        print("Usage: %s <bin_file>" % (sys.argv[0]))
        return

    filename = sys.argv[1]
    # 读取二进制文件存放到list列表中
    bindata = open(filename, 'rb').read()
    offset = 0
    fmt = '>B'
    binListData = []
    while offset < len(bindata):
        unpackdata = struct.unpack_from(fmt, bindata, offset)
        binListData.append("0x%.2x" % unpackdata[0])
        offset += struct.calcsize(fmt)

    ## 将列表中的数据写入到 .c 源文件中
    fileoutname = os.path.splitext(filename)[0] + '_arry.c'
    print("write to C array file %s" % fileoutname)
    with open(fileoutname, 'w') as fileOutput:
        fileOutput.write("unsigned long hexDataLength = {};\n".format(len(binListData)))
        fileOutput.write("unsigned char hexData[] = {\n")
        for i in range(len(binListData) - 1):
            if (i != 0) and (i % 16 == 0):
                fileOutput.write("\n")
            fileOutput.write(binListData[i] + ",")
        fileOutput.write(binListData[len(binListData) - 1] + "\n};")
    print("bin to C array success!")


if __name__ == '__main__':
    bin2hex()

脚本使用方法:

python3 bin2hex.py <binfile>

生成 binfile_arry.c 16进制数组

16进制数组转二进制bit流

此外,提供一个16进制数组转为二进制bit流的脚本:

# hexarray2bin
"""
将数组文件转换成二进制流bin文件
"""
import sys, os
import struct

def hexarray2bin():
    if len(sys.argv) != 2:
        print("Usage: %s <hex_array_file>" % (sys.argv[0]))
        return

    filename = sys.argv[1]
    # 读取数组存放到列表中
    data_tmp = []
    with open(filename, 'r') as fdata:
        lines = fdata.readlines()

    for line in lines:
        for i in line.strip().split(','):
            if i.isalnum():
                data_tmp.append(int(i, 16))

    ## 将列表中的数据写入到 .bin 二进制流中
    fileoutname = os.path.splitext(filename)[0] + '.bin'
    print("write to bin file %s" % fileoutname)

    fmt = ">%uI" % len(data_tmp)
    with open(fileoutname, 'wb') as fileOutput:
        bin_stream = struct.pack(fmt, *data_tmp)
        fileOutput.write(bin_stream)

    print("C array to bin success!")


if __name__ == '__main__':
    hexarray2bin()

数组文件如下(手动去头去尾):

0xfcff0000,0xfcff0000,0x00000000,0x00000000,0x0000fcff,0x00000000,0xfcff0000,0x0000f8ff,
0xf8fff8ff,0xf8fff8ff,0xfcfffcff,0xfcfffcff,0xfcfffcff,0xfcfffcff,0xfcfffcff,0xfcfffcff,
...

然后调用脚本:

python3 hexarray2bin <hexarrayfile>

生成 hexarrayfile.bin 二进制bit流数组

参考:

  1. Python使用struct处理二进制
  2. python将二进制数据的bin文件转换成16进制数组形式的C源文件
  3. struct — Interpret bytes as packed binary data — Python 3.11.3 documentation

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/201890.html

(0)
小半的头像小半

相关推荐

极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!