
Python 以 rb 模式读取文件时返回的是 bytes 对象,但直接转为字符串(如 str())会触发 Unicode 解码,导致不可见字符被错误解释或合并;实际字节值并未损坏,只需避免误转换并使用合适方式展示。
python 以 `rb` 模式读取文件时返回的是 `bytes` 对象,但直接转为字符串(如 `str()`)会触发 unicode 解码,导致不可见字符被错误解释或合并;实际字节值并未损坏,只需避免误转换并使用合适方式展示。
当你用 open('tree.sgi', 'rb') 打开文件,并执行 f.read(24),返回的确实是原始的 24 字节数据(类型为 bytes)。问题根源在于你调用了 str(f.read(byteAdressEnd)) —— 这会将 bytes 对象强制转换为字符串,Python 会尝试用默认编码(通常是 UTF-8)解码这些字节。而二进制文件中大量非 UTF-8 合法字节序列(如 \xb0、\x83、\x91 等)会被解释为无效或代理字符,甚至引发 UnicodeDecodeError;某些字节(如 \x76 对应 ASCII 'v')则被“美化”显示为可读字符,造成你观察到的“字节被合并为字符”的错觉——这并非读取错误,而是显示/转换逻辑造成的视觉干扰。
✅ 正确做法:始终直接操作 bytes 对象,避免无意义的 str() 转换。例如:
with open('tree.sgi', 'rb') as f:
data = f.read(24) # data 是 bytes 类型,保持原始字节
print(type(data)) # <class 'bytes'>
print(data) # 输出类似: b'\x01\xda\x01\x01\x00\x03\x04\xb0\x02v\x00\x03\x00\x00\x00\x00\x00\x00\x00\xff\x00\x00\x00\x00'⚠️ 注意:print(data) 默认以可读形式显示(ASCII 可打印字符显示为字母,其余显示为 \xXX),这是 bytes.__repr__() 的行为,完全安全且忠实于原始数据。
若需统一以十六进制格式清晰查看所有字节(如调试二进制协议),推荐以下更健壮的打印函数:
立即学习“Python免费学习笔记(深入)”;
def hexdump(data: bytes, sep=' ') -> str:
"""将 bytes 转为十六进制字符串,如 '01 da 01 01 00 ...'"""
return sep.join(f'{b:02x}' for b in data)
# 使用示例
with open('tree.sgi', 'rb') as f:
data = f.read(24)
print(hexdump(data)) # 输出: 01 da 01 01 00 03 04 b0 02 76 00 03 00 00 00 00 00 00 00 ff 00 00 00 00? 关键总结:
- ✅ rb 模式读取绝对可靠,bytes 对象即原始字节,无需“修复”;
- ❌ 避免 str(bytes_obj),这是绝大多数显示异常的根源;
- ✅ 使用 bytes.hex()(返回无分隔符十六进制字符串)或自定义 hexdump 函数进行可视化;
- ✅ 处理二进制数据时,优先使用 struct.unpack()、int.from_bytes() 等方法解析结构化内容,而非字符串操作。


















