Py学习  »  Python

Python struct库:5分钟学会读懂任何二进制文件

A逍遥之路 • 2 周前 • 32 次点击  

今天来分享这个"神奇"的struct库,它能让你轻松处理各种二进制文件。

struct库到底是干什么的?

简单说,struct库就是Python和二进制数据之间的"翻译官"。

你知道吗?计算机里的所有文件,不管是图片、音频、视频还是游戏存档,本质上都是一堆0和1组成的二进制数据。而struct库就能帮我们把这些看不懂的二进制数据,转换成我们能理解的数字、字符串等。

反过来,它也能把我们的数据"打包"成二进制格式保存到文件里。

基础用法:pack和unpack

1. 打包数据(pack)

import struct
# 把整数和浮点数打包成二进制数据data = struct.pack('if'12343.14)print(data)  # b'\xd2\x04\x00\x00\xc3\xf5H@'print(len(data))  # 8字节

这里的'if'是格式字符串:

  • 'i' 表示一个4字节的整数

  • 'f' 表示一个4字节的浮点数

2. 解包数据(unpack)

import struct
# 假设我们有一些二进制数据binary_data = b'\xd2\x04\x00\x00\xc3\xf5H@'
# 解包出原来的数据num, pi = struct.unpack('if', binary_data)print(f"整数: {num}")    # 整数: 1234print(f"浮点数: {pi}")   # 浮点数: 3.140000104904175

实战应用:读取BMP图片的基本信息

想知道一张BMP图片的宽度和高度吗?用struct库几行代码就搞定:

import struct
def read_bmp_info(filename):    with open(filename, 'rb'as f:        # 读取BMP文件头(前54字节)        header = f.read(54)
        # 检查是否是BMP文件        if header[:2] != b'BM':            print("这不是BMP文件!" )            return
        # 从第18字节开始读取宽度和高度(各4字节)        width, height = struct.unpack(', header[18:26])
        print(f"图片宽度: {width} 像素")        print(f"图片高度: {height} 像素")
# 使用方法(需要有一个test.bmp文件)# read_bmp_info('test.bmp')

注意 中的 < 表示小端字节序,I 表示无符号整数。

解析网络数据包

如果你对网络编程感兴趣,struct在解析网络协议时特别有用:

import struct
def parse_ip_header(packet_data):    # 解析IP数据包头部(简化版)    # 前20字节包含IP头部信息    ip_header = struct.unpack('!BBHHHBBH4s4s', packet_data[:20])
    version = ip_header[0] >> 4  # IP版本    protocol = ip_header[6]      # 协议类型    src_ip = ip_header[8]        # 源IP(二进制)    dst_ip = ip_header[9]        # 目标IP(二进制)
    print(f"IP版本: {version}")    print(f"协议: {protocol}")
    # 将二进制IP转换为可读格式    import socket    src_ip_str = socket.inet_ntoa(src_ip)    dst_ip_str = socket.inet_ntoa(dst_ip)
    print(f"源IP: {src_ip_str}")    print(f"目标IP: {dst_ip_str}")
# 这个函数需要真实的网络数据包才能测试

处理传感器数据

假设你有一个温湿度传感器,每次发送8字节的数据:

import structimport time
def simulate_sensor_data():    """模拟传感器发送的二进制数据"""    temperature = 25.6  # 温度    humidity = 60.3     # 湿度    timestamp = int(time.time())  # 时间戳
    # 打包数据:2个浮点数 + 1个整数    data = struct.pack('ffi', temperature, humidity, timestamp)    return data
def parse_sensor_data(binary_data):     """解析传感器数据"""    temp, humid, ts = struct.unpack('ffi', binary_data)
    print(f"温度: {temp:.1f}°C")    print(f"湿度: {humid:.1f}%")    print(f"时间: {time.ctime(ts)}")
# 模拟数据传输sensor_data = simulate_sensor_data()print("收到传感器数据,正在解析...")parse_sensor_data(sensor_data)

常用格式字符速查表

格式字符C类型Python类型大小(字节)说明
bsigned charint1有符号字节
Bunsigned charint1 无符号字节
hshortint2短整型
Hunsigned shortint2无符号短整型
iintint4整型
Iunsigned intint4无符号整型
ffloatfloat4单精度浮点
ddoublefloat8双精度浮点
schar[]bytes-字符串

字节序说明

  • @ 或不写:本机字节序

  • =:本机字节序

  • <:小端字节序(Intel处理器常用)

  • >:大端字节序(网络字节序)

  • !:网络字节序(大端)

实用技巧

1. 计算结构体大小

import struct
# 计算格式字符串对应的字节数size = struct.calcsize('ifi')print(f"数据大小: {size} 字节")  # 12字节

2. 处理可变长度数据

import struct
def pack_string(text):    """打包字符串:先存长度,再存内容"""    text_bytes = text.encode('utf-8')    length = len(text_bytes)    return struct.pack(f'I{length}s', length, text_bytes)
def unpack_string(data):    """解包字符串"""    length = struct.unpack('I', data[:4])[0]    text_bytes = struct.unpack(f'{length}s', data[4:4+length])[0]    return text_bytes.decode('utf-8')
# 测试original = "Hello Python!"packed = pack_string(original)unpacked = unpack_string(packed)print(f"原文: {original}")print(f"解包后: {unpacked}")

错误处理

使用struct时要注意数据长度匹配:

import struct
try:    # 错误:数据长度不匹配    struct.unpack('ii'b'\x01\x02\x03')  # 需要8字节,只给了3字节except struct.error as e:    print(f"解包错误: {e}")
try:    # 正确的做法    data = b'\x01\x02\x03\x04\x05\x06\x07\x08'    result = struct.unpack('ii', data)    print(f"解包成功: {result}")except struct.error as e:    print(f"解包错误: {e}")

struct库看起来复杂,其实就做两件事:

  1. pack:把Python数据变成二进制

  2. unpack:把二进制变成Python数据

掌握了这两个函数,你就能:

  • 解析各种文件格式

  • 处理网络协议数据

  • 与C语言程序交换数据

  • 优化数据存储

学习建议

  1. 从简单开始:先练习整数和浮点数的打包解包

  2. 理解字节序:网络编程时特别重要

  3. 多做实验:用不同的格式字符串试试效果

  4. 结合实际:找个具体的文件格式来练手

转发、收藏、在看,是对作者最大的鼓励!👏
关注逍遥不迷路,Python知识日日补!






           对Python,AI,自动化办公提效,副业发展等感兴趣的伙伴们,扫码添加逍遥,限免交流群

备注【成长交流】

图片

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/184004
 
32 次点击