Преобразование строки с прямым порядком байтов в целое число

Я читал семплы из волнового файла с помощью модуля wave, но он выдает семплы в виде строки, это не волна, поэтому порядок следования байтов (например, \x00).

Каков самый простой способ преобразовать это в целое число python или тип numpy.int16? (В конечном итоге он станет numpy.int16, так что идти прямо туда можно).

Код должен работать на процессорах с прямым и обратным порядком байтов.


person Jeffrey Aylesworth    schedule 08.11.2009    source источник
comment
Общий случай: stackoverflow.com/questions/444591/   -  person Mechanical snail    schedule 22.05.2013


Ответы (4)


Модуль struct преобразует упакованные данные в значения Python и наоборот.

>>> import struct
>>> struct.unpack("<h", "\x00\x05")
(1280,)
>>> struct.unpack("<h", "\x00\x06")
(1536,)
>>> struct.unpack("<h", "\x01\x06")
(1537,)

"h" означает короткое целое или 16-битное целое. «‹» означает использование прямого порядка байтов.

person Ned Batchelder    schedule 08.11.2009
comment
Для python3 вам нужно сначала преобразовать строку в байты struct.unpack("<h", bytes("\x00\x06", "utf8")) - person Sir l33tname; 24.09.2016

struct подходит, если вам нужно преобразовать одну или небольшое количество 2-байтовых строк в целые числа, но лучше использовать array и numpy. В частности, numpy.fromstring (вызывается с соответствующим dtype аргумент) может напрямую преобразовать байты из вашей строки в массив (независимо от того, что это dtype). (Если numpy.little_endian равно false, вам придется поменять местами байты — см. здесь для более подробного обсуждения, но в основном вы захотите вызвать метод byteswap для объекта массива, который вы только что создали с помощью fromstring).

person Alex Martelli    schedule 08.11.2009
comment
Это также действительно полезно знать, но я собираюсь использовать структурное решение, так что мне не нужно беспокоиться об исправлении порядка следования байтов вручную. - person Jeffrey Aylesworth; 09.11.2009
comment
Если вы никуда не спешите или у вас очень мало точек данных, это нормально. В противном случае вы можете закодировать порядок байтов как строку как часть dtype (хотя я не знаю подробностей навскидку). - person Alex Martelli; 09.11.2009

Ответ Кевина Берка на этот вопрос прекрасно работает, когда ваша двоичная строка представляет собой одно короткое целое число, но если ваша строка содержит двоичные данные, представляющие несколько целых чисел, вам нужно будет добавить дополнительный 'h' для каждого дополнительного целого числа, которое представляет строка.

Для Python 2

Преобразование строки с прямым порядком байтов, представляющей 2 целых числа

import struct
iValues = struct.unpack("<hh", "\x00\x04\x01\x05")
print(iValues)

Вывод: (1024, 1281)

Преобразование строки с прямым порядком байтов, представляющей 3 целых числа

import struct
iValues = struct.unpack("<hhh", "\x00\x04\x01\x05\x03\x04")
print(iValues)

Вывод: (1024, 1281, 1027)

Очевидно, что всегда нереально угадать, сколько символов «h» необходимо, поэтому:

import struct

# A string that holds some unknown quantity of integers in binary form
strBinary_Values = "\x00\x04\x01\x05\x03\x04"

# Calculate the number of integers that are represented by binary string data
iQty_of_Values = len(strBinary_Values)/2

# Produce the string of required "h" values
h = "h" * int(iQty_of_Values)

iValues = struct.unpack("<"+h, strBinary_Values)
print(iValues)

Вывод: (1024, 1281, 1027)

Для Python 3

import struct

# A string that holds some unknown quantity of integers in binary form
strBinary_Values = "\x00\x04\x01\x05\x03\x04"

# Calculate the number of integers that are represented by binary string data
iQty_of_Values = len(strBinary_Values)/2

# Produce the string of required "h" values
h = "h" * int(iQty_of_Values)

iValues = struct.unpack("<"+h, bytes(strBinary_Values, "utf8"))
print(iValues)

Вывод: (1024, 1281, 1027)

person David M. Helmuth    schedule 26.12.2018

int(value[::-1].hex(), 16)

Например:

value = b'\xfd\xff\x00\x00\x00\x00\x00\x00'
print(int(value[::-1].hex(), 16))
65533

[::-1] инвертировать значения (с прямым порядком байтов), .hex() преобразовывать в шестнадцатеричный литерал, int(,16) преобразовывать из шестнадцатеричного литерала в int base16.

person e-info128    schedule 02.11.2020