我有一个二进制整数的字符串表示,我需要具有精确位结构的字节,以通过套接字发送。
例如如果我有一个长度为16的字符串:0000111100001010
那么我需要2个字节的相同位结构。在这种情况下,第一个字节的int值应为15
,第二个字节应为10
。它们是否可以ascii
格式打印并不重要。我怎么得到它?
我尝试了以下方法,它以0xf0xa
的形式创建字节。但这个大小为6个字节而不是2个。
def getByte(s):
if(len(s) != 8):
return
b = b'0'
for c in s:
b = (int(b) | int(c)) & 0x0000ff #This makes b an integer
b = b << 1
b = b >> 1 #because of 1 extra shift
b = hex(b).encode('utf-8') #how else can I get back to byte from int?
return(b)
此方法采用长度为8的字符串,并打算提供相同内部位结构的字节,但失败。 (我需要strtol
中与C
类似的内容。)
请帮忙吗?
答案 0 :(得分:6)
首先,如果您将位字符串作为文字值,只需将其设为base-2 int literal,而不是字符串文字:
value = 0b0000111100001010
如果您有非文字位字符串,并且您需要做的就是将它们解析为整数,那么,正如martineau在评论中所说,内置的int
构造函数就是您所需要的,如martineau说,因为它需要base
作为可选的第二个参数:
value = int('0000111100001010', 2)
如果您需要使用位字符串做任何奇特的事情,您可能希望使用第三方模块,如bitarray
或bitstring
,这样可以创建可被视为字符串的对象1和0,布尔序列,整数等:
value = bitstring.BitArray(bin='0000111100001010')
一旦你有一个整数,你可以用struct
将它打包成2个字节,正如martineau在评论中所解释的那样:
my_bytes = struct.pack('!H', value)
!
表示“network-endian”。如果您想要little-endian或native-endian(或big-endian,当然与network-endian相同,但可能是描述某些上下文的更有意义的方式),请参阅Byte Order, Size, and Alignment。 H
表示将其打包为C unsigned short
- 即两个字节。
但如果您使用的是第三方模块,它可能会更简单。例如,如果您有前一个示例中的bitstring.BitArray
:
my_bytes = value.tobytes()
答案 1 :(得分:4)
转换二进制字符串数据的简单方法就是使用内置的int()
函数,并告诉它数字是基数为2的二进制而不是默认的基数10十进制格式:
int('0000111100001010', 2)
这将返回一个整数值。要将其转换为字节字符串,可以使用pack()
模式中的struct
函数,并使用格式将数据参数称为short
(2字节)无符号整数字符串'H'
:
struct.pack('!H', int('0000111100001010', 2))
由于你想通过网络套接字发送它,我还添加了一个'!'
前缀,表示返回的字节应该是“网络”或大端字节顺序而不是本机格式你的电脑(可能不同)。
请注意,为示例返回的字符串为'\x0f\n'
。最后的'\n'
是因为字节值0x0a
碰巧是一个ASCII换行符,所以当Python显示包含一个字符串的repr()
时,它就是这样表示的(这是Python交互式控制台在每个表达式后自动执行的操作。)