Я использую следующий метод для чтения двоичных данных из любого заданного смещения в двоичном файле. Двоичный файл у меня есть огромный 10GB, так что я обычно читаю ее часть, когда это необходимо, указав, из которых компенсировано я должен start_read
и сколько байт для чтения num_to_read
. Я использую Python 3.6.4 :: Anaconda, Inc.
, платформу Darwin-17.6.0-x86_64-i386-64bit
и os- модуль:
def read_from_disk(path, start_read, num_to_read, dim):
fd = os.open(path, os.O_RDONLY)
os.lseek(fd, start_read, 0) # Where to (start_read) from the beginning 0
raw_data = os.read(fd, num_to_read) # How many bytes to read
C = np.frombuffer(raw_data, dtype=np.int64).reshape(-1, dim).astype(np.int8)
os.close(fd)
return C
Этот метод работает очень хорошо, когда кусок данных для чтения составляет менее 2 ГБ. Когда num_to_read > 2GG
, я получаю эту ошибку:
raw_data = os.read(fd, num_to_read) # How many to read (num_to_read)
OSError: [Errno 22] Invalid argument
Я не уверен, почему возникает эта проблема и как ее исправить. Любая помощь высоко ценится.
Функция os.read
- это всего лишь тонкая оболочка вокруг функции read
платформы.
На некоторых платформах это неподписанный или подписанный 32-битный int, 1, что означает, что наибольшее число, которое вы можете read
за один проход на этих платформах, составляет соответственно 4 ГБ или 2 ГБ.
Итак, если вы хотите больше читать, и вы хотите быть кросс-платформенным, вам нужно написать код для обработки этого и буферизовать несколько файлов read
.
Это может быть немного больно, но вы намеренно используете функцию прямого сопоставления непосредственно для отображения в OS-API. Если вам это не нравится:
io
модуля (Python 3.x) или объекты file
(2.7), которые вы вернетесь из open
.mmap
(если вы на 64-битной платформе).Правильная вещь здесь - это почти наверняка сочетание первых двух. В Python 3 это будет выглядеть так:
with open(path, 'rb', buffering=0) as f:
f.seek(start_read)
count = num_to_read // 8 # how many int64s to read
return np.fromfile(f, dtype=np.int64, count=count).reshape(-1, dim).astype(np.int8)
1. Для Windows, функция _read
библиотеки _read
-эмуляции использует int
для аргумента count, который подписан 32-битным.Для любой другой современной платформы, см POSIX read
, а затем посмотреть определения size_t
, ssize_t
и off_t
, на вашей платформе.Обратите внимание, что на многих платформах POSIX есть отдельные 64-битные типы и соответствующие функции вместо изменения значения существующих типов на 64-разрядные.Python будет использовать стандартные типы, а не специальные 64-битные типы.
num_to_read
в вашем коде? Это очень важно для меня, так как я не хочу читать весь файл, только его часть