#python #parsing #floating-point #binaryfiles #ieee-754
#python #синтаксический анализ #с плавающей запятой #двоичные файлы #ieee-754
Вопрос:
У меня есть двоичный файл, который представляет собой простой список подписанных 32-разрядных чисел с плавающей запятой ieee754. Они ничем не разделены и просто отображаются один за другим до EOF.
Как бы я прочитал из этого файла и правильно интерпретировал их как числа с плавающей запятой?
Я пытался использовать read(4)
, но он автоматически преобразует их в строку с кодировкой ascii.
Я также пытался использовать bytearray
, но это занимает только 1 байт за раз вместо 4 байт за раз, как мне нужно.
Ответ №1:
struct.unpack('f', file.read(4))
Вы также можете распаковать несколько одновременно, что будет быстрее:
struct.unpack('f'*n, file.read(4*n))
Комментарии:
1. 1 для ‘f’ * n; где задокументирован этот синтаксис? Должно быть, я пропустил это в моем учебном пособии по Python.
2. Умножение строк описано в руководстве и в справочном разделе библиотеки по объектам sequence.
3. Более общим способом распаковки нескольких было бы
unpack('{0}f'.format(n), ...)
, или, если вы знаете, сколько заранее, тогда простоunpack('10f', ...)
, например. Лучше использовать встроенный метод повторения, чем полагаться на манипулирование строками.4. @cdiggins: Я склоняюсь к тому, что требует наименьшего количества ввода и легче всего читается. Эти два фактора иногда конфликтуют, поэтому вам, возможно, придется заменить один другим, но в этом случае моя версия и короче, и понятнее. С точки зрения производительности я ожидаю, что две формы будут почти идентичны, поскольку основная часть времени тратится в подсистеме ввода-вывода. Если длина известна во время кодирования, то я согласен, что
'10f'
это лучше, точно по тем же причинам: это немного короче и легче для чтения, чем'f'*10
.5. @Marcelo, я согласен с принципом, но рассмотрите возможность распаковки 100 000 целых чисел. Для меня не имеет смысла создавать строку формата длиной 100 кб. Вместо ‘{0}f’.формат (1000000) имеет больше смысла.
Ответ №2:
Взгляните на struct.распакуйте. Может сработать что-то вроде следующего…
f = struct.unpack('f', data_read)
Ответ №3:
import struct
(num,) = struct.unpack('f', f.read(4))
Ответ №4:
Самый быстрый подход (с точки зрения производительности) Пока я обнаружил, что это numpy.fromfile
import numpy as np
class FloatReader:
def __init__(self, filename):
self.f = open(filename, "rb")
def read_floats(self, count : int):
return np.fromfile(self.f, dtype=np.float32, count=count, sep='')
Этот подход намного быстрее, чем struct.unpack
с точки зрения производительности!