struct.unpack格式串中途切换字节序的问题求助
struct Unpack for Game Save Data Ah, I’ve been there before—mixing endianness in struct unpacks is one of those tricky gotchas that trips up a lot of people, especially with game save files which often throw little-endian and big-endian integers together. Let’s break down what’s happening and how to fix it.
First, the core issue: Python’s struct module does not support per-field endianness markers. Those <, >, !, and = markers are global to the entire format string—you can’t toggle them mid-string (like trying <i!I for a little-endian int followed by a big-endian int). That’s why you got that vague error; the module sees conflicting/ invalid format syntax and doesn’t know how to parse it.
The fix is to split your binary data into chunks aligned by their endianness, then unpack each chunk with the correct format string separately. Here’s how to do it properly:
Example 1: Basic Mixed Endian Parsing
Suppose your save data has a 4-byte little-endian integer (player health) followed by a 4-byte big-endian integer (high score):
import struct # Sample raw binary data: little-endian 1, big-endian 2 raw_save_data = b'\x01\x00\x00\x00\x00\x00\x00\x02' # Split into chunks and unpack each with the right endianness player_health = struct.unpack('<i', raw_save_data[:4])[0] high_score = struct.unpack('!I', raw_save_data[4:8])[0] print(player_health) # Output: 1 print(high_score) # Output: 2
Example 2: Batch Processing Same-Endian Fields
If you have multiple consecutive fields using the same endianness, you can unpack them in one go to save code:
# Sample data: little-endian int + big-endian short + big-endian int raw_save_data = b'\x01\x00\x00\x00\x00\x03\x00\x00\x00\x04' # Unpack little-endian chunk first player_health = struct.unpack('<i', raw_save_data[:4])[0] # Unpack consecutive big-endian fields together weapon_id, total_coins = struct.unpack('!HI', raw_save_data[4:10]) print(f"Health: {player_health}, Weapon ID: {weapon_id}, Coins: {total_coins}") # Output: Health: 1, Weapon ID: 3, Coins: 4
Pro Tip: Organize Field Specs for Readability
For game saves with dozens of fields, create a list of field specifications to keep your code clean and maintainable:
field_specs = [ (0, 4, '<i', 'player_health'), (4, 8, '!I', 'high_score'), (8, 10, '<h', 'weapon_id'), (10, 14, '!f', 'world_position_x'), ] parsed_save = {} for start, end, fmt, field_name in field_specs: parsed_save[field_name] = struct.unpack(fmt, raw_save_data[start:end])[0] # Access parsed values like parsed_save['high_score']
Why Global Endianness Markers Cause Flip Issues
If you tried using a single format string with one endianness marker (e.g., <iI), the second integer would be parsed as little-endian too—completely mangling your big-endian value. The only way to avoid this is to split the data and handle each endianness group separately.
内容的提问来源于stack exchange,提问作者Quuxplusone

