Как читать часть двоичного файла с numpy?
Я преобразовываю matlab script в numpy, но имею некоторые проблемы с чтением данных из двоичного файла. Есть ли equivelent to fseek
при использовании fromfile
, чтобы пропустить начало файла? Это тип экстракций, которые мне нужно сделать:
fid = fopen(fname);
fseek(fid, 8, 'bof');
second = fread(fid, 1, 'schar');
fseek(fid, 100, 'bof');
total_cycles = fread(fid, 1, 'uint32', 0, 'l');
start_cycle = fread(fid, 1, 'uint32', 0, 'l');
Спасибо!
Ответы
Ответ 1
Вы можете использовать поиск с файловым объектом обычным способом, а затем использовать этот файл в fromfile
. Вот полный пример:
import numpy as np
import os
data = np.arange(100, dtype=np.int)
data.tofile("temp") # save the data
f = open("temp", "rb") # reopen the file
f.seek(256, os.SEEK_SET) # seek
x = np.fromfile(f, dtype=np.int) # read the data into numpy
print x
# [64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88
# 89 90 91 92 93 94 95 96 97 98 99]
Ответ 2
Вероятно, лучший ответ... Но когда я столкнулся с этой проблемой, у меня был файл, который я уже хотел получить в разных частях отдельно, что дало мне легкое решение этой проблемы.
Например, скажем chunkyfoo.bin
- это файл, состоящий из 6-байтового заголовка, массива размером 1024 байта numpy
и еще одного 1024-байтового массива numpy
. Вы не можете просто открыть файл и искать 6 байтов (потому что первая вещь numpy.fromfile
делает это lseek
назад к 0). Но вы можете просто mmap
использовать этот файл и вместо него использовать fromstring
:
with open('chunkyfoo.bin', 'rb') as f:
with closing(mmap.mmap(f.fileno(), length=0, access=mmap.ACCESS_READ)) as m:
a1 = np.fromstring(m[6:1030])
a2 = np.fromstring(m[1030:])
Это похоже на то, что вы хотите сделать. Кроме того, конечно, что в реальной жизни смещение и длина до a1
и a2
, вероятно, зависят от заголовка, а не от фиксированных комментариев.
Заголовок - это просто m[:6]
, и вы можете разобрать его, явно раздвинув его, используя модуль struct
или что-нибудь еще, что вы сделали бы, выполнив read
данные. Но, если вы предпочитаете, вы можете явно seek
и read
из f
перед конструированием m
, или после, или даже сделать те же вызовы на m
, и он будет работать, не затрагивая a1
и a2
.
Альтернативой, которую я сделал для другого проекта, не связанного с numpy
, является создание объекта файла-обертки, например:
class SeekedFileWrapper(object):
def __init__(self, fileobj):
self.fileobj = fileobj
self.offset = fileobj.tell()
def seek(self, offset, whence=0):
if whence == 0:
offset += self.offset
return self.fileobj.seek(offset, whence)
# ... delegate everything else unchanged
Я сделал "делегировать все остальное без изменений", создав атрибут list
атрибутов во время построения и используя это в __getattr__
, но вы, вероятно, хотите что-то менее хакерское. numpy
зависит только от нескольких методов файлового объекта, и я думаю, что они правильно документированы, поэтому просто делегируйте их. Но я думаю, что решение mmap
имеет больше смысла здесь, если вы не пытаетесь механически переносить кучу явного кода seek
. (Вы думаете, что mmap
также предоставит вам возможность оставить его как numpy.memmap
вместо numpy.array
, что позволяет numpy
иметь больше контроля над/обратную связь от поискового вызова и т.д. Но это на самом деле довольно сложно получить команды numpy.memmap
и mmap
для совместной работы.)
Ответ 3
Это то, что я делаю, когда мне приходится читать произвольное в гетерогенном двоичном файле.
Numpy позволяет интерпретировать битовый шаблон в режиме арбитража путем изменения dtype массива.
Код Matlab в вопросе читает a char
и два uint
.
Прочтите эту статью (простое чтение на уровне пользователя, а не для ученых) о том, что можно достичь с изменением dtype, шага, размерности массив.
import numpy as np
data = np.arange(10, dtype=np.int)
data.tofile('f')
x = np.fromfile('f', dtype='u1')
print x.size
# 40
second = x[8]
print 'second', second
# second 2
total_cycles = x[8:12]
print 'total_cycles', total_cycles
total_cycles.dtype = np.dtype('u4')
print 'total_cycles', total_cycles
# total_cycles [2 0 0 0] !endianness
# total_cycles [2]
start_cycle = x[12:16]
start_cycle.dtype = np.dtype('u4')
print 'start_cycle', start_cycle
# start_cycle [3]
x.dtype = np.dtype('u4')
print 'x', x
# x [0 1 2 3 4 5 6 7 8 9]
x[3] = 423
print 'start_cycle', start_cycle
# start_cycle [423]