从"无符号"字节流中读取32位有符号值

4 投票
3 回答
5011 浏览
提问于 2025-04-17 12:42

我想从一个文件中提取数据,这个文件里的信息是以大端格式存储的,并且总是是无符号的。请问将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)

撰写回答