Как читать целые числа из файла с 24-битным и байтовым порядком байтов с использованием Python?

Есть ли простой способ прочитать эти целые числа в? Я бы предпочел встроенный метод, но я предполагаю, что это возможно сделать с некоторыми битовыми операциями.
ура

редактировать
Я подумал о другом способе сделать это, который отличается от способов ниже и, на мой взгляд, более понятен. Он дополняется нулями на другом конце, затем сдвигает результат. Нет, если требуется, потому что смещение заполняет то, чем изначально является msb.

struct.unpack('<i','\0'+ bytes)[0] >> 8
 John Machin29 сент. 2010 г., 03:48
+1 на ваше редактирование.

Ответы на вопрос(4)

тогда мойбитовая модуль может быть полезен здесь.

from bitstring import ConstBitStream
s = ConstBitStream(filename='some_file')
a = s.read('uintle:24')

Это читает первые 24 бита и интерпретирует его как беззнаковое целое число с прямым порядком байтов. После прочтенияs.pos установлен в 24 (битовая позиция в потоке), так что вы можете прочитать больше. Например, если вы хотите получить список из следующих 10 целых чисел со знаком, вы можете использовать

l = s.readlist('10*intle:24')

или, если вы предпочитаете, вы можете просто использовать кусочки и свойства и не беспокоиться о чтениях:

a = s[0:24].uintle

Другой вариант, если у вас уже есть 3 байта данных из вашего файла, это просто создать и интерпретировать:

a = ConstBitStream(bytes=b'abc').uintle
 Scott Griffiths25 сент. 2010 г., 15:57
@jolly: если производительность вызывает беспокойство, то вам следует придерживатьсяstruct метод. Bitstring (на данный момент) чистый Python, поэтому он не победит. Это достаточно эффективно, но основной упор делался на то, чтобы сделать побитовые задачи как можно проще, а не настолько быстро, насколько это возможно - по крайней мере, пока :)
 simonb25 сент. 2010 г., 01:30
Я бы предпочел не использовать внешнюю библиотеку для этого конкретного проекта, но, тем не менее, я проверю это. Какова производительность для чего-то подобного? Потенциально они будут работать со скоростью 3 Мбит / с, так что их будет 130 000 каждую секунду. Честно говоря, частота дискретизации намного выше необходимой, поэтому я могу просто отбросить большинство из них, но если я не справлюсь с этой библиотекой?
Решение Вопроса

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

Если вы прочитали одно трехбайтовое число из файла, вы можете преобразовать его следующим образом:

struct.unpack('<I', bytes + '\0')

Модуль не поддерживает 24-битные слова, поэтому'\0'-padding.

РЕДАКТИРОВАТЬ: Подписанные номера хитрее. Вы можете скопировать старший бит и установить старший бит на ноль, потому что он перемещается на самое высокое место из 4 байтов (последний\xff есть это).:

struct.unpack('<i', bytes + ('\0' if bytes[2] < '\x80' else '\xff'))

Или для python3 (bytes является зарезервированным словом, проверка байта массива байтов даетint):

struct.unpack('<i', chunk + ('\0' if chunk[2] < 128 else '\xff'))
 simonb24 сент. 2010 г., 04:10
Спасибо, но я забыл сказать, что они подписаны, так что заполнение самых значимых битов не сработает, так как справедливо мое ограниченное понимание дополнения двух.
 John Machin24 сент. 2010 г., 04:27
Для большей ясности и скорости попробуйте.... if bytes[2] < '\x80' else ....
 Marcelo Cantos24 сент. 2010 г., 04:16
@jolly: я исправил свой ответ соответственно.
 Marcelo Cantos24 сент. 2010 г., 12:54
@ Джон: Глупый я. Спасибо за улучшение.
 simonb24 сент. 2010 г., 04:27
Круто, большое спасибо.

ттлдиан?

struct.unpack('<I', bytes + '\x00')[0] # unsigned littleendian
struct.unpack('>I', '\x00' + bytes)[0] # unsigned bigendian

Signed немного сложнее ... получите значение без знака, как указано выше, затем сделайте следующее:

signed = unsigned if not (unsigned & 0x800000) else unsigned - 0x1000000
 simonb24 сент. 2010 г., 04:29
Извини, приятель, не видел тебя там внизу. Очевидно, у меня недостаточно репутации, чтобы поддержать, но спасибо за усилия!

но вот кое-что, что может быть полезно в этой ситуации. Он основан на обновленном ответе OP, но интегрирует его в функцию, которая считывает весь список значений из упакованного файла с 24-битными значениями. Он делает это в основном со структурой, поэтому я думаю, что это должно быть достаточно быстро.

  def int24_to_int(self, input_data):
    bytelen = len(input_data)
    frames = bytelen/3
    triads = struct.Struct('3s' * frames)
    int4byte = struct.Struct('<i')
    result = [int4byte.unpack('\0' + i)[0] >> 8 for i in triads.unpack(input_data)]
    return result

Ваш ответ на вопрос