5

我有一个二进制整数的字符串表示,我需要具有确切位结构的字节来通过套接字发送。

例如,如果我有一个长度为 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 的字符串,并打算给出相同内部位结构的字节,但失败了。(我需要类似于strtolin 的东西C。)

请问有什么帮助吗?

4

2 回答 2

9

首先,如果您将位字符串作为文字值,只需将其设为 base-2 int 文字,而不是字符串文字:

value = 0b0000111100001010

如果您有非文字位字符串,并且您需要做的就是将它们解析为整数,那么正如 martineau 在评论中所说,内置int构造函数就是您所需要的,正如 martineau 所说,因为它需要 abase作为可选的第二个参数:

value = int('0000111100001010', 2)

bitarray如果您需要对位字符串做任何花哨的事情,您可能需要使用像or这样的第三方模块bitstring,它可以让您创建可以被视为 1 和 0 字符串、布尔序列、整数等的对象。 :

value = bitstring.BitArray(bin='0000111100001010')

一旦你有了一个整数,你可以用 将它打包成 2 个字节struct,正如 martineau 在评论中解释的那样:

my_bytes = struct.pack('!H', value)

意思是“!网络端”。如果您想要 little-endian 或 native-endian(或 big-endian,这当然与 network-endian 相同,但可能是描述某些上下文的更有意义的方式),请参阅Byte Order, Size, and Alignment。将H其打包为 C的方法unsigned short——即两个字节。


但是,如果您使用的是第三方模块,它可能会更简单一些。例如,如果您有bitstring.BitArray上一个示例中的一个:

my_bytes = value.tobytes()
于 2013-04-25T00:30:18.957 回答
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 交互式控制台在每个表达式之后自动执行的操作)。

于 2013-04-25T01:05:34.847 回答