将字符串字节转换为int (python)

时间:2021-12-30 18:15:45

How can I convert a string of bytes into an int in python?

如何将一串字节转换成python中的整数?

Say like this: 'y\xcc\xa6\xbb'

像这样说:‘y \ xcc \ xa6 \ xbb”

I came up with a clever/stupid way of doing it:

我想出了一个聪明/愚蠢的方法:

sum(ord(c) << (i * 8) for i, c in enumerate('y\xcc\xa6\xbb'[::-1]))

I know there has to be something builtin or in the standard library that does this more simply...

我知道必须有一些东西,或者在标准库中,这样做更简单……

This is different from converting a string of hex digits for which you can use int(xxx, 16), but instead I want to convert a string of actual byte values.

这不同于转换一串十六进制数字,您可以使用int(xxx, 16),但是我想要转换一个字符串的实际字节值。

UPDATE:

更新:

I kind of like James' answer a little better because it doesn't require importing another module, but Greg's method is faster:

我有点喜欢James的回答,因为它不需要导入另一个模块,但是Greg的方法更快:

>>> from timeit import Timer
>>> Timer('struct.unpack("<L", "y\xcc\xa6\xbb")[0]', 'import struct').timeit()
0.36242198944091797
>>> Timer("int('y\xcc\xa6\xbb'.encode('hex'), 16)").timeit()
1.1432669162750244

My hacky method:

我的出租汽车司机的方法:

>>> Timer("sum(ord(c) << (i * 8) for i, c in enumerate('y\xcc\xa6\xbb'[::-1]))").timeit()
2.8819329738616943

FURTHER UPDATE:

进一步更新:

Someone asked in comments what's the problem with importing another module. Well, importing a module isn't necessarily cheap, take a look:

有人在评论中问导入另一个模块有什么问题。嗯,导入一个模块不一定便宜,看一下:

>>> Timer("""import struct\nstruct.unpack(">L", "y\xcc\xa6\xbb")[0]""").timeit()
0.98822188377380371

Including the cost of importing the module negates almost all of the advantage that this method has. I believe that this will only include the expense of importing it once for the entire benchmark run; look what happens when I force it to reload every time:

包括导入模块的成本几乎抵消了该方法的所有优点。我认为,这只会包括一次性导入整个基准测试的费用;看看我强迫它每次重新加载时会发生什么:

>>> Timer("""reload(struct)\nstruct.unpack(">L", "y\xcc\xa6\xbb")[0]""", 'import struct').timeit()
68.474128007888794

Needless to say, if you're doing a lot of executions of this method per one import than this becomes proportionally less of an issue. It's also probably i/o cost rather than cpu so it may depend on the capacity and load characteristics of the particular machine.

不用多说,如果你在执行这个方法的过程中执行了很多次操作,那么这个问题就不成比例了。它也可能是i/o成本而不是cpu,因此它可能取决于特定机器的容量和负载特性。

10 个解决方案

#1


81  

You can also use the struct module to do this:

你也可以使用struct模块来做这个:

>>> struct.unpack("<L", "y\xcc\xa6\xbb")[0]
3148270713L

#2


214  

In Python 3.2 and later, use

在Python 3.2和之后,使用。

>>> int.from_bytes(b'y\xcc\xa6\xbb', byteorder='big')
2043455163

or

>>> int.from_bytes(b'y\xcc\xa6\xbb', byteorder='little')
3148270713

according to the endianness of your byte-string.

根据你的字节字符串的字节。

This also works for bytestring-integers of arbitrary length, and for two's-complement signed integers by specifying signed=True. See the docs for from_bytes.

这也适用于任意长度的bytestring-integer,并通过指定签名=True来满足两个整数签名的整数。请参阅from_bytes的文档。

#3


59  

As Greg said, you can use struct if you are dealing with binary values, but if you just have a "hex number" but in byte format you might want to just convert it like:

正如Greg所说,如果你在处理二进制值,你可以使用struct,但是如果你有一个“十六进制数字”,但是在字节格式中,你可能想要转换成:

s = 'y\xcc\xa6\xbb'
num = int(s.encode('hex'), 16)

...this is the same as:

…这是一样的:

num = struct.unpack(">L", s)[0]

...except it'll work for any number of bytes.

…除非它适用于任意数量的字节。

#4


7  

I use the following function to convert data between int, hex and bytes.

我使用以下函数来转换int、十六进制和字节之间的数据。

def bytes2int(str):
 return int(str.encode('hex'), 16)

def bytes2hex(str):
 return '0x'+str.encode('hex')

def int2bytes(i):
 h = int2hex(i)
 return hex2bytes(h)

def int2hex(i):
 return hex(i)

def hex2int(h):
 if len(h) > 1 and h[0:2] == '0x':
  h = h[2:]

 if len(h) % 2:
  h = "0" + h

 return int(h, 16)

def hex2bytes(h):
 if len(h) > 1 and h[0:2] == '0x':
  h = h[2:]

 if len(h) % 2:
  h = "0" + h

 return h.decode('hex')

Source: http://opentechnotes.blogspot.com.au/2014/04/convert-values-to-from-integer-hex.html

来源:http://opentechnotes.blogspot.com.au/2014/04/convert-values-to-from-integer-hex.html

#5


6  

import array
integerValue = array.array("I", 'y\xcc\xa6\xbb')[0]

Warning: the above is strongly platform-specific. Both the "I" specifier and the endianness of the string->int conversion are dependent on your particular Python implementation. But if you want to convert many integers/strings at once, then the array module does it quickly.

警告:以上是特定于平台的。“I”说明符和string->int转换的发现都依赖于您的特定Python实现。但是,如果您想要同时转换多个整数/字符串,则数组模块可以快速地进行转换。

#6


4  

In Python 2.x, you could use the format specifiers <B for unsigned bytes, and <b for signed bytes with struct.unpack/struct.pack.

在Python中2。您可以使用格式说明符 来表示无符号的字节,而

E.g:

例句:

Let x = '\xff\x10\x11'

让x = \ xff \ x10 \ x11的

data_ints = struct.unpack('<' + 'B'*len(x), x) # [255, 16, 17]

data_ints =结构。unpack('<' + 'B'*len(x), x) # [255, 16, 17]

And:

和:

data_bytes = struct.pack('<' + 'B'*len(data_ints), *data_ints) # '\xff\x10\x11'
That * is required!

data_bytes =结构。包('<' + 'B'*len(data_ints), *data_ints) # '\xff\x10\x11',这是必需的!

See https://docs.python.org/2/library/struct.html#format-characters for a list of the format specifiers.

请参阅https://docs.python.org/2/library/struct.html#format-字符列表的格式说明符。

#7


1  

int.from_bytes is the best solution if you are at version >=3.2. The "struct.unpack" solution requires a string so it will not apply to arrays of bytes. Here is another solution:

如果您在版本>=3.2中,from_bytes是最好的解决方案。“结构。解包“解决方案需要一个字符串,所以它不会应用于字节数组。这是另一个解决方案:

def bytes2int( tb, order='big'):
    if order == 'big': seq=[0,1,2,3]
    elif order == 'little': seq=[3,2,1,0]
    i = 0
    for j in seq: i = (i<<8)+tb[j]
    return i

hex( bytes2int( [0x87, 0x65, 0x43, 0x21])) returns '0x87654321'.

hex(bytes2int([0x87, 0x65, 0x43, 0x21])返回'0x87654321'。

It handles big and little endianness and is easily modifiable for 8 bytes

它处理的是大而小的发现,并且很容易修改为8个字节。

#8


1  

>>> reduce(lambda s, x: s*256 + x, bytearray("y\xcc\xa6\xbb"))
2043455163

Test 1: inverse:

测试1:逆:

>>> hex(2043455163)
'0x79cca6bb'

Test 2: Number of bytes > 8:

测试2:字节数> 8:

>>> reduce(lambda s, x: s*256 + x, bytearray("AAAAAAAAAAAAAAA"))
338822822454978555838225329091068225L

Test 3: Increment by one:

测试3:增加1:

>>> reduce(lambda s, x: s*256 + x, bytearray("AAAAAAAAAAAAAAB"))
338822822454978555838225329091068226L

Test 4: Append one byte, say 'A':

测试4:追加一个字节,说“A”:

>>> reduce(lambda s, x: s*256 + x, bytearray("AAAAAAAAAAAAAABA"))
86738642548474510294585684247313465921L

Test 5: Divide by 256:

测试5:除以256:

>>> reduce(lambda s, x: s*256 + x, bytearray("AAAAAAAAAAAAAABA"))/256
338822822454978555838225329091068226L

Result equals the result of Test 4, as expected.

结果等于测试4的结果,如预期的那样。

#9


1  

As mentioned above using unpack function of struct is a good way. If you want to implement your own function there is an another solution:

如上所述,使用struct的unpack函数是一种很好的方法。如果你想实现你自己的功能,还有另一个解决方案:

def bytes_to_int(bytes):
    result = 0
    for b in bytes:
        result = result * 256 + int(b)
return result

#10


0  

I was struggling to find a solution for arbitrary length byte sequences that would work under Python 2.x. Finally I wrote this one, it's a bit hacky because it performs a string conversion, but it works.

我一直在努力寻找一个可以在Python 2.x下工作的任意长度字节序列的解决方案。最后我写了这个,它有点hacky,因为它执行了一个字符串转换,但是它是有效的。

Function for Python 2.x, arbitrary length

def signedbytes(data):
    """Convert a bytearray into an integer, considering the first bit as
    sign. The data must be big-endian."""
    negative = data[0] & 0x80 > 0

    if negative:
        inverted = bytearray(~d % 256 for d in data)
        return -signedbytes(inverted) - 1

    encoded = str(data).encode('hex')
    return int(encoded, 16)

This function has two requirements:

这个功能有两个要求:

  • The input data needs to be a bytearray. You may call the function like this:

    输入数据需要是一个bytearray。你可以这样称呼它:

    s = 'y\xcc\xa6\xbb'
    n = signedbytes(s)
    
  • The data needs to be big-endian. In case you have a little-endian value, you should reverse it first:

    这些数据必须是大数据。如果你的值很小,你应该先把它反转过来:

    n = signedbytes(s[::-1])
    

Of course, this should be used only if arbitrary length is needed. Otherwise, stick with more standard ways (e.g. struct).

当然,这应该只在需要任意长度时才使用。否则,就用更标准的方法(比如struct)。

#1


81  

You can also use the struct module to do this:

你也可以使用struct模块来做这个:

>>> struct.unpack("<L", "y\xcc\xa6\xbb")[0]
3148270713L

#2


214  

In Python 3.2 and later, use

在Python 3.2和之后,使用。

>>> int.from_bytes(b'y\xcc\xa6\xbb', byteorder='big')
2043455163

or

>>> int.from_bytes(b'y\xcc\xa6\xbb', byteorder='little')
3148270713

according to the endianness of your byte-string.

根据你的字节字符串的字节。

This also works for bytestring-integers of arbitrary length, and for two's-complement signed integers by specifying signed=True. See the docs for from_bytes.

这也适用于任意长度的bytestring-integer,并通过指定签名=True来满足两个整数签名的整数。请参阅from_bytes的文档。

#3


59  

As Greg said, you can use struct if you are dealing with binary values, but if you just have a "hex number" but in byte format you might want to just convert it like:

正如Greg所说,如果你在处理二进制值,你可以使用struct,但是如果你有一个“十六进制数字”,但是在字节格式中,你可能想要转换成:

s = 'y\xcc\xa6\xbb'
num = int(s.encode('hex'), 16)

...this is the same as:

…这是一样的:

num = struct.unpack(">L", s)[0]

...except it'll work for any number of bytes.

…除非它适用于任意数量的字节。

#4


7  

I use the following function to convert data between int, hex and bytes.

我使用以下函数来转换int、十六进制和字节之间的数据。

def bytes2int(str):
 return int(str.encode('hex'), 16)

def bytes2hex(str):
 return '0x'+str.encode('hex')

def int2bytes(i):
 h = int2hex(i)
 return hex2bytes(h)

def int2hex(i):
 return hex(i)

def hex2int(h):
 if len(h) > 1 and h[0:2] == '0x':
  h = h[2:]

 if len(h) % 2:
  h = "0" + h

 return int(h, 16)

def hex2bytes(h):
 if len(h) > 1 and h[0:2] == '0x':
  h = h[2:]

 if len(h) % 2:
  h = "0" + h

 return h.decode('hex')

Source: http://opentechnotes.blogspot.com.au/2014/04/convert-values-to-from-integer-hex.html

来源:http://opentechnotes.blogspot.com.au/2014/04/convert-values-to-from-integer-hex.html

#5


6  

import array
integerValue = array.array("I", 'y\xcc\xa6\xbb')[0]

Warning: the above is strongly platform-specific. Both the "I" specifier and the endianness of the string->int conversion are dependent on your particular Python implementation. But if you want to convert many integers/strings at once, then the array module does it quickly.

警告:以上是特定于平台的。“I”说明符和string->int转换的发现都依赖于您的特定Python实现。但是,如果您想要同时转换多个整数/字符串,则数组模块可以快速地进行转换。

#6


4  

In Python 2.x, you could use the format specifiers <B for unsigned bytes, and <b for signed bytes with struct.unpack/struct.pack.

在Python中2。您可以使用格式说明符 来表示无符号的字节,而

E.g:

例句:

Let x = '\xff\x10\x11'

让x = \ xff \ x10 \ x11的

data_ints = struct.unpack('<' + 'B'*len(x), x) # [255, 16, 17]

data_ints =结构。unpack('<' + 'B'*len(x), x) # [255, 16, 17]

And:

和:

data_bytes = struct.pack('<' + 'B'*len(data_ints), *data_ints) # '\xff\x10\x11'
That * is required!

data_bytes =结构。包('<' + 'B'*len(data_ints), *data_ints) # '\xff\x10\x11',这是必需的!

See https://docs.python.org/2/library/struct.html#format-characters for a list of the format specifiers.

请参阅https://docs.python.org/2/library/struct.html#format-字符列表的格式说明符。

#7


1  

int.from_bytes is the best solution if you are at version >=3.2. The "struct.unpack" solution requires a string so it will not apply to arrays of bytes. Here is another solution:

如果您在版本>=3.2中,from_bytes是最好的解决方案。“结构。解包“解决方案需要一个字符串,所以它不会应用于字节数组。这是另一个解决方案:

def bytes2int( tb, order='big'):
    if order == 'big': seq=[0,1,2,3]
    elif order == 'little': seq=[3,2,1,0]
    i = 0
    for j in seq: i = (i<<8)+tb[j]
    return i

hex( bytes2int( [0x87, 0x65, 0x43, 0x21])) returns '0x87654321'.

hex(bytes2int([0x87, 0x65, 0x43, 0x21])返回'0x87654321'。

It handles big and little endianness and is easily modifiable for 8 bytes

它处理的是大而小的发现,并且很容易修改为8个字节。

#8


1  

>>> reduce(lambda s, x: s*256 + x, bytearray("y\xcc\xa6\xbb"))
2043455163

Test 1: inverse:

测试1:逆:

>>> hex(2043455163)
'0x79cca6bb'

Test 2: Number of bytes > 8:

测试2:字节数> 8:

>>> reduce(lambda s, x: s*256 + x, bytearray("AAAAAAAAAAAAAAA"))
338822822454978555838225329091068225L

Test 3: Increment by one:

测试3:增加1:

>>> reduce(lambda s, x: s*256 + x, bytearray("AAAAAAAAAAAAAAB"))
338822822454978555838225329091068226L

Test 4: Append one byte, say 'A':

测试4:追加一个字节,说“A”:

>>> reduce(lambda s, x: s*256 + x, bytearray("AAAAAAAAAAAAAABA"))
86738642548474510294585684247313465921L

Test 5: Divide by 256:

测试5:除以256:

>>> reduce(lambda s, x: s*256 + x, bytearray("AAAAAAAAAAAAAABA"))/256
338822822454978555838225329091068226L

Result equals the result of Test 4, as expected.

结果等于测试4的结果,如预期的那样。

#9


1  

As mentioned above using unpack function of struct is a good way. If you want to implement your own function there is an another solution:

如上所述,使用struct的unpack函数是一种很好的方法。如果你想实现你自己的功能,还有另一个解决方案:

def bytes_to_int(bytes):
    result = 0
    for b in bytes:
        result = result * 256 + int(b)
return result

#10


0  

I was struggling to find a solution for arbitrary length byte sequences that would work under Python 2.x. Finally I wrote this one, it's a bit hacky because it performs a string conversion, but it works.

我一直在努力寻找一个可以在Python 2.x下工作的任意长度字节序列的解决方案。最后我写了这个,它有点hacky,因为它执行了一个字符串转换,但是它是有效的。

Function for Python 2.x, arbitrary length

def signedbytes(data):
    """Convert a bytearray into an integer, considering the first bit as
    sign. The data must be big-endian."""
    negative = data[0] & 0x80 > 0

    if negative:
        inverted = bytearray(~d % 256 for d in data)
        return -signedbytes(inverted) - 1

    encoded = str(data).encode('hex')
    return int(encoded, 16)

This function has two requirements:

这个功能有两个要求:

  • The input data needs to be a bytearray. You may call the function like this:

    输入数据需要是一个bytearray。你可以这样称呼它:

    s = 'y\xcc\xa6\xbb'
    n = signedbytes(s)
    
  • The data needs to be big-endian. In case you have a little-endian value, you should reverse it first:

    这些数据必须是大数据。如果你的值很小,你应该先把它反转过来:

    n = signedbytes(s[::-1])
    

Of course, this should be used only if arbitrary length is needed. Otherwise, stick with more standard ways (e.g. struct).

当然,这应该只在需要任意长度时才使用。否则,就用更标准的方法(比如struct)。