如何使用Python从24位和小端的文件中读取整数?

时间:2010-09-24 01:45:24

标签: python file-io endianness

有没有简单的方法来读取这些整数?我更喜欢内置方法,但我认为可以做一些位操作 干杯

修改
我想到了另一种方式,这与下面的方式不同,在我看来更清楚。它在另一端用零填充,然后移动结果。如果需要,则为“否”,因为使用msb最初的移动填充。

struct.unpack('<i','\0'+ bytes)[0] >> 8

5 个答案:

答案 0 :(得分:12)

Python的struct模块允许您将字节解释为不同类型的数据结构,并控制字节顺序。

如果您从文件中读取一个三字节数字,则可以进行转换:

struct.unpack('<I', bytes + '\0')

该模块似乎不支持24位字,因此'\0' - 填充。

编辑:签名号码比较棘手。您可以复制高位,并将高位设置为零,因为它移动到4个字节的最高位置(最后\xff有它)。:

struct.unpack('<i', bytes + ('\0' if bytes[2] < '\x80' else '\xff'))

或者,对于python3(bytes是保留字,检查字节数组的字节给出int):

struct.unpack('<i', chunk + ('\0' if chunk[2] < 128 else '\xff'))

答案 1 :(得分:7)

您的24位整数是签名还是未签名? Bigendian或littleendian?

struct.unpack('<I', bytes + '\x00')[0] # unsigned littleendian
struct.unpack('>I', '\x00' + bytes)[0] # unsigned bigendian

签名稍微复杂一点......如上所述获取无符号值,然后执行此操作:

signed = unsigned if not (unsigned & 0x800000) else unsigned - 0x1000000

答案 2 :(得分:4)

如果您不介意使用外部库,那么我的bitstring模块可能会对您有所帮助。

from bitstring import ConstBitStream
s = ConstBitStream(filename='some_file')
a = s.read('uintle:24')

读取前24位并将其解释为无符号小端整数。读取s.pos设置为24(流中的位位置)后,您可以阅读更多内容。例如,如果您想获得下一个10个有符号整数的列表,可以使用

l = s.readlist('10*intle:24')

或者如果您愿意,您可以使用切片和属性,而不必阅读:

a = s[0:24].uintle

如果您已经拥有来自您文件的3个字节的数据,那么另一个选择就是创建和解释:

a = ConstBitStream(bytes=b'abc').uintle

答案 3 :(得分:2)

有点晚了,但在这种情况下这里有用。它建立在OP的更新答案之上,但将其集成到一个函数中,该函数从24位整数的打包文件中读出整个值列表。它主要使用struct,所以我认为它应该相当快。

  def int24_to_int(self, input_data):
    bytelen = len(input_data)
    frames = bytelen/3
    triads = struct.Struct('3s' * frames)
    int4byte = struct.Struct('<i')
    result = [int4byte.unpack('\0' + i)[0] >> 8 for i in triads.unpack(input_data)]
    return result

答案 4 :(得分:0)

Python 3方法

在Python 3中,我更喜欢使用int.from_bytes()将3字节表示形式转换为32位整数。无需填充。

value = int.from_bytes(input_data[0:3],'big',signed=True)

或者只是

value = int.from_bytes(input_data)

如果您的数组只有3个字节,并且默认为表示形式。