从"无符号"字节流中读取32位有符号值
我想从一个文件中提取数据,这个文件里的信息是以大端格式存储的,并且总是是无符号的。请问将unsigned int转换成int会对实际的十进制值产生什么影响?我理解的对吗?最左边的那一位决定了这个值是正数还是负数吗?
我想用Python来解析这种文件格式,读取一个无符号值是很简单的:
def toU32(bits):
return ord(bits[0]) << 24 | ord(bits[1]) << 16 | ord(bits[2]) << 8 | ord(bits[3])
但是对应的toS32函数应该是什么样子的呢?
谢谢你提供的关于struct模块的信息。不过我还是想知道关于我实际问题的解决方案。
3 个回答
0
toS32(bits)这个函数的非条件版本可以写成这样:
def toS32(bits):
decoded = toU32(bits)
return -(decoded & 0x80000000) + (decoded & 0x7fffffff)
当然,你也可以提前计算出其他位数的掩码。
0
我会使用 struct模块 的打包和解包方法。
可以查看 Python中整数的字节序 来了解一些例子。
10
我会使用 struct 这个模块。
import struct
def toU32(bits):
return struct.unpack_from(">I", bits)[0]
def toS32(bits):
return struct.unpack_from(">i", bits)[0]
这里的格式字符串 ">I" 的意思是从字符串的二进制数据中读取一个大端格式的无符号整数。符号 ">" 表示大端格式,而 "I" 则表示无符号整数。如果你想读取有符号整数,可以用 ">i"。
编辑
我需要去看另一个 StackOverflow 上的 回答,才想起来如何在 Python 中把一个无符号整数“转换”为有符号整数。其实这并不是简单的转换,更像是重新解释这些二进制位。
import struct
def toU32(bits):
return ord(bits[0]) << 24 | ord(bits[1]) << 16 | ord(bits[2]) << 8 | ord(bits[3])
def toS32(bits):
candidate = toU32(bits);
if (candidate >> 31): # is the sign bit set?
return (-0x80000000 + (candidate & 0x7fffffff)) # "cast" it to signed
return candidate
for x in range(-5,5):
bits = struct.pack(">i", x)
print toU32(bits)
print toS32(bits)