[Python]_[初级]_[使用struct库对二进制文件进行读写]

本文介绍Python中如何使用struct库处理二进制数据,包括数据打包与解包的操作方法,并通过具体示例展示了如何读写二进制文件。

场景

1.要分析或生成一个二进制文件时, Python使用 struct库来转换或分析二进制数据. 当然使用C++或者Java来分析也可以, 但对于脚本语言Python来说, 编写数据和调试时间都没Python快. 所以Python其实是比较正确的选择.

2.如果需要传输socket数据, 在定义好数据格式时自然也是使用stuct.pack和unpack来打包数据和分析数据.

说明

1.Python作为一门通用型脚本语言, 能像Java,C++那样处理通用型任务,比如读写二进制或文本文件. 读写文本文件很容易, 使用File Object即可操作, 读取字符串一般使用file.readline 或者 file.readlines, 一个是返回字符串对象, 一个是返回一个列表.

2.Python使用字符串对象存储二进制数据. 当调用file.read(n) 时, 返回一个字符串对象, 这个字符串对象类似于C++的 std::string 或者 char buf[], 都可以存储任何字节数据; 当需要对string对象,即字节数据进行操作时, 就需要unpack来进行数据转换, 比如把4个字节转换为数值, 把某部分的字节转换为str()字符串等等. Python的file对象类似于 C语言的FILE对象, 差不多有类似的对应函数.

3.对于struct.pack和unpack的说明, 其中 pack其实是对C结构体进行打包, 并进行本机默认地址对齐, 本地字节序. 比如 “bci” 的大小是8. 所以尽量使用i, 而不是b,c这些单字节, 因为被对齐后大小很难计算.

struct.pack(fmt, v1, v2, ...) 
Return a string containing the values v1, v2, ... packed according to the given format. The arguments must match the values required by the format exactly

struct.unpack(fmt, string) 
Unpack the string (presumably packed by pack(fmt, ...)) according to the given format. The result is a tuple even if it contains exactly one item. The string must contain exactly the amount of data required by the format (len(string) must equal calcsize(fmt)).

4.Byte Order, Size, and Alignment

CharacterByte orderSizeAlignment
@nativenativenative
=nativestandardnone
<little-endianstandardnone
>big-endianstandardnone
!network(= big-endian)standard

5.Format Characters

FormatC TypePython typeStandard sizeNotes
xpadbytenovalue
ccharstring of length11
bsigned charinteger1(3)
Bunsigned charinteger1(3)
?_Boolbool1(1)
hshortinteger2(3)
Hunsigned shortinteger2(3)
iintinteger4(3)
Iunsigned intinteger4(3)
llonginteger4(3)
Lunsigned longinteger4(3)
qlong longinteger8(2), (3)
Qunsigned long longinteger8(2), (3)
ffloatfloat4(4)
ddoublefloat8(4)
schar[]string
pchar[]string
Pvoid *integer(5), (3)

例子

#! encoding=utf8

import sys
import os
import io
from StringIO import  StringIO
from struct import unpack
from struct import pack

def TestWriter(path):
    f = open(path,"wb")

    # write png header
    header = pack('BBBB',0x89,0x50,0x4E,0x47)
    f.write(header)

    one_str = "string中文"
    one_char1 = 0
    one_char2 = ord('t')
    one_int = 50
    # we need calc string length
    str_len = len(one_str)
    format = '%dsiii' % (str_len)
    body = pack(format,one_str,one_char1,one_char2,one_int)
    print len(body)

    f.write(body)
    f.close()

def TestReader(path):
    f = open(path,"rb")
    header = f.read(1)
    a, = unpack("B",header)
    png = f.read(3)
    print png

    name=''
    n=f.read(1)
    while unpack('<b',n)[0]!=0:
        name=name+str(n)
        n=f.read(1)

    print name
    # three bytes. == 0
    f.seek(3,io.SEEK_CUR)

    left = f.read(8)
    a,b = unpack("ii",left)
    print "%d:%d" % (a,b)

    f.close()

if __name__ == '__main__':
    path = ""
    if len(sys.argv) > 1:
        path = sys.argv[1];
    else:
        path = "temp.png"

    TestWriter(path);
    TestReader(path);
    # os.remove(path)

输出

24
PNG
string中文
116:50

参考

struct – Interpret strings as packed binary data
Python使用struct处理二进制
File Objects

`struct` 模块在 Python 中用于处理结构化数据,特别是二进制数据读写操作。你可以使用这个模块来定义数据的结构,然后根据这些结构从文件或内存中读取和写入数据。 如果你想用 `struct` 读写包含“王涛机械11128”这样的文本字符串的二进制文件,通常情况下,你会先将字符串转换为字节序列(如果尚未这样做),因为 `struct` 需要直接处理二进制数据。这里假设你有一个名为 "filename.txt" 的文件,你可以按照以下步骤进行: ```python import struct # 假设原始文本存储在 'data' 变量中 data = '王涛机械11128' # 将文本转换为字节串 (UTF-8编码) byte_data = data.encode('utf-8') # 定义结构体格式,这里我们简单地使用固定大小的字符数组 format_code = '8s' # 's' 表示字符串,'8' 表示长度为8个字符(包括终止符) # 写入文件 with open("output.bin", "wb") as file: struct.pack_into(format_code, file, 0, byte_data) # 读取文件 with open("output.bin", "rb") as file: # 使用pack函数从文件读取并解析数据 read_bytes = file.read(struct.calcsize(format_code)) read_str = struct.unpack_from(format_code, read_bytes)[0].decode('utf-8') print(f"Read from file: {read_str}") ``` 这段代码首先将文本转换成字节串,然后使用 `struct.pack_into` 将其写入文件,接着用 `struct.unpack_from` 来从文件中读回数据。请注意,如果你的文本可能有不同长度,上述格式可能需要修改,例如使用变长字符串 (`'{length}s'`) 或者计算实际字符串长度的方式。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

白行峰 (花名)

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

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

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

打赏作者

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

抵扣说明:

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

余额充值