2015-09-23 2 views
6

Мне нужно читать и писать огромные двоичные файлы. есть ли предпочтительное или даже оптимальное количество байтов (что я называю BLOCK_SIZE), я должен read() за раз?предпочтительный размер блока при чтении/записи больших двоичных файлов

1 байт, конечно, мало; и я не думаю, что чтение 4 ГБ в ОЗУ - хорошая идея - есть ли «лучший» размер блока? или это даже зависит от файловой системы (я на ext4)? что мне нужно учитывать?

python's open() также содержит аргумент buffering. мне тоже нужно было бы настроить его?

это пример кода, который просто соединяет два файла in-0.data и in-1.data в out.data (в реальной жизни есть более обработка, которая не имеет никакого отношения к рассматриваемому вопросу). BLOCK_SIZE выбирается равной io.DEFAULT_BUFFER_SIZE, который, как представляется, по умолчанию для buffering:

from pathlib import Path 
from functools import partial 

DATA_PATH = Path(__file__).parent/'../data/' 

out_path = DATA_PATH/'out.data' 
in_paths = (DATA_PATH/'in-0.data', DATA_PATH/'in-1.data') 

BLOCK_SIZE = 8192 

def process(data): 
    pass 

with out_path.open('wb') as out_file: 
    for in_path in in_paths: 
     with in_path.open('rb') as in_file: 
      for data in iter(partial(in_file.read, BLOCK_SIZE), b''): 
       process(data) 
       out_file.write(data) 
#   while True: 
#    data = in_file.read(BLOCK_SIZE) 
#    if not data: 
#     break 
#    process(data) 
#    out_file.write(data) 
+0

Не уверен, что для этого есть определенный ответ, вероятно, зависящий от ОС, файловой системы и физического диска на рассматриваемой машине. Если это предназначено для общего решения, вы можете добавить код для опроса системы параметров для расчета наилучшего ответа. – cdkMoose

+0

Я надеялся «опросить систему» ​​с помощью 'io.DEFAULT_BUFFER_SIZE' - но у меня действительно нет опыта с деталями всего этого ... –

+1

Нет единого статического ответа для этого даже в данной системе. Это зависит от большого числа переменных, некоторые из которых могут меняться со временем или быть разными каждый раз. а также то, что еще делает ваша программа или система. Лучшим подходом может стать написать что-то, чтобы определить хороший размер в тот момент, используя определенные неизменные репрезентативные тестовые файлы. В качестве альтернативы вы можете написать автономный тест и запустить его один раз, чтобы получить хорошую оценку, а затем жестко запрограммировать ваше приложение (или сделать тестовую часть процесса установки или настройки). – martineau

ответ

4

Пусть OS принять решение для Вас. Используйте модуль MMAP:

https://docs.python.org/3.4/library/mmap.html

Он использует базовый механизм отображения памяти вашей операционной системы для отображения содержимого файла в оперативную память.

Помните, что при использовании 32-разрядного Python существует ограничение размера файла 2 ГБ, поэтому используйте 64-битную версию, если вы решите пройти этот маршрут.

Например:

f1 = open('input_file', 'r+b') 
m1 = mmap.mmap(f1.fileno(), 0) 
f2 = open('out_file', 'a+b') # out_file must be >0 bytes on windows 
m2 = mmap.mmap(f2.fileno(), 0) 
m2.resize(len(m1)) 
m2[:] = m1 # copy input_file to out_file 
m2.flush() # flush results 

Обратите внимание, что вы никогда не должны были вызвать любое чтение() функцию и решить, сколько байт, чтобы принести в оперативную память. Этот пример просто копирует один файл в другой, но, как вы сказали в своем примере, вы можете делать любую обработку, в которой вы нуждаетесь. Обратите внимание: если весь файл сопоставляется с адресным пространством в ОЗУ, это не означает, что он действительно был скопирован там. Он будет скопирован кусочно, по усмотрению ОС.

+0

Если я правильно понял, мне все равно нужно было бы определить количество байтов 'n', которые хотели бы [' read ([n]) '] (https://docs.python.org/3.4/library/ mmap.html # mmap.mmap.read). то я вернусь к своей первоначальной проблеме. или что мне не хватает? –

+0

Я сейчас пытаюсь использовать некоторый код, но по существу mmap предоставляет вам интерфейс bytearray для ваших данных, в дополнение к файловому интерфейсу. Таким образом, вы можете получить доступ, обрабатывать и т. Д. Ваши данные, как если бы они были уже в байтах. –

+0

Как получить прибыль от 'bytearray'? мои 'данные' относятся к типу' 'уже, что отлично подходит для того, что мне нужно. но мне интересно посмотреть, куда это идет! –

Смежные вопросы