在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 语法的 width
和 type
部分。 8
将 width
设置为 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 对象?