在python中将字节转换为位

Posted

技术标签:

【中文标题】在python中将字节转换为位【英文标题】:Convert bytes to bits in python 【发布时间】:2012-02-07 14:12:07 【问题描述】:

我正在使用 Python3.2。我需要将十六进制流作为输入并在位级解析它。所以我用了

bytes.fromhex(input_str)

将字符串转换为实际字节。现在如何将这些字节转换为位?

【问题讨论】:

字节是位,一次只有 8 个 ;) - 答案取决于你想做什么,请更具体一点。位操作主要是在字节级别上完成的...... 我想以位字符串的形式表示字节,以便我可以执行以下操作:field1 = bit_string[0:1] field2 = bit_string[1:16] 等等 【参考方案1】:

另一种方法是使用bitstring 模块:

>>> from bitstring import BitArray
>>> input_str = '0xff'
>>> c = BitArray(hex=input_str)
>>> c.bin
'0b11111111'

如果你需要去掉前面的0b

>>> c.bin[2:]
'11111111'

bitstring 模块不是必需的,正如 jcollado 的回答所示,但它有许多高效的方法可以将输入转换为位并对其进行操作。您可能会觉得这很方便(或不方便),例如:

>>> c.uint
255
>>> c.invert()
>>> c.bin[2:]
'00000000'

等等

【讨论】:

+1。对于最新版本的位串(3.0),您不需要剥离前导0b【参考方案2】:

当您在整数级别工作时,操作会快得多。特别是,按照这里的建议转换为字符串真的很慢。

如果您只需要第 7 位和第 8 位,请使用例如

val = (byte >> 6) & 3

(这是:将字节向右移动 6 位 - 丢弃它们。然后只保留最后两位 3 是设置了前两位的数字...)

这些可以很容易地转化为超级快速的简单 CPU 操作。

【讨论】:

【参考方案3】:

这样的事情呢?

>>> bin(int('ff', base=16))
'0b11111111'

这会将您拥有的十六进制字符串转换为整数,并将该整数转换为字符串,其中每个字节设置为 0/1,具体取决于整数的位值。

正如评论所指出的,如果您需要摆脱0b 前缀,您可以这样做:

>>> bin(int('ff', base=16)).lstrip('0b')
'11111111'

或者这样:

>>> bin(int('ff', base=16))[2:]
'11111111'

【讨论】:

lstrip('-0b') # 去掉前导零和减号 @ahoffer 感谢您的评论。我已经更新了我的答案,让 OP 知道如何删除 0b 前缀。 请注意,lstrip('0b') 也将删除,例如,00bb,因为 lstrip 的参数是要删除的 字符。在这种情况下它会正常工作,但我更喜欢[2:] 解决方案,因为它更明确。 @MartinGeisler 是的,bin 在转换为整数时已经删除了前导零,但值得注意的是,lstrip 删除了一组字符,而不是前缀。【参考方案4】:

使用pythonformat string syntax

>>> mybyte = bytes.fromhex("0F") # create my byte using a hex string
>>> binary_string = ":08b".format(int(mybyte.hex(),16))
>>> print(binary_string)
00001111

第二行是魔法发生的地方。所有字节对象都有一个.hex() 函数,它返回一个十六进制字符串。使用这个十六进制字符串,我们将其转换为整数,告诉int() 函数它是一个基数为 16 的字符串(因为十六进制是基数 16)。然后我们对该整数应用格式,使其显示为二进制字符串。 :08b 是真正神奇的地方。它使用Format Specification Mini-Languageformat_spec。具体来说,它使用了 format_spec 语法的 widthtype 部分。 8width 设置为 8,这就是我们获得漂亮的 0000 填充的方式,b 将类型设置为二进制。

我更喜欢这种方法而不是 bin() 方法,因为使用格式字符串提供了更多的灵活性。

【讨论】:

但是这种方法不允许您将可变数量的字节作为输入,对吧?您需要硬编码最终的二进制字符串需要多长时间。【参考方案5】:

我认为最简单的方法是在这里使用numpy。例如,您可以将文件读取为字节,然后像这样轻松地将其扩展为位:

Bytes = numpy.fromfile(filename, dtype = "uint8")
Bits = numpy.unpackbits(Bytes)

【讨论】:

【参考方案6】:

转二进制:

bin(byte)[2:].zfill(8)

【讨论】:

您不能使用 bin 转换字节。【参考方案7】:

读取读取字节时使用ord

byte_binary = bin(ord(f.read(1))) # Add [2:] to remove the "0b" prefix

或者

使用str.format()

':08b'.format(ord(f.read(1)))

【讨论】:

【参考方案8】:

这里如何使用format()

print "bin_signedDate : ", ''.join(format(x, '08b') for x in bytevector)

08b 很重要。这意味着将最多附加 8 个前导零来完成一个字节。如果你不指定这个,那么格式对于每个转换的字节只有一个可变的位长度。

【讨论】:

【参考方案9】:
input_str = "ABC"
[bin(byte) for byte in bytes(input_str, "utf-8")]

将给予:

['0b1000001', '0b1000010', '0b1000011']

【讨论】:

【参考方案10】:

此处的其他答案按big-endian 顺序提供位('\x01' 变为'00000001'

如果您对位的小端顺序感兴趣,这在许多情况下很有用,例如大数字的常见表示等 - 这是一个sn-p:

def bits_little_endian_from_bytes(s):
    return ''.join(bin(ord(x))[2:].rjust(8,'0')[::-1] for x in s)

而对于另一个方向:

def bytes_from_bits_little_endian(s):
    return ''.join(chr(int(s[i:i+8][::-1], 2)) for i in range(0, len(s), 8))

【讨论】:

以上是关于在python中将字节转换为位的主要内容,如果未能解决你的问题,请参考以下文章

将字节数组转换为位集

在python中将字节转换为BufferedReader [重复]

在 Python 中将字节转换为 BufferedReader 对象?

如何在python中将纯文本转换为分段块(字节)? [复制]

在python中将字节转换为文件对象

在 Python 3 中将 int 转换为字节