2010-08-21 5 views
3

Каков наиболее эффективный способ удаления произвольного фрагмента файла с учетом начальных и конечных смещений? Я бы предпочел использовать Python, но я могу вернуться к C, если придется.Удаление произвольного фрагмента файла

Say файл это

..............xxxxxxxx---------------- 

Я хочу, чтобы удалить кусок его:

..............[xxxxxxxx]---------------- 

После операции он должен стать:

..............---------------- 

Чтение все это в память и манипулирование им в памяти не представляется возможным.

+3

ли вы имеете в виду на месте удаления (храбрый), или вы скопировать соответствующие части в новый файл, переименовать старый файл, переименовать новый файл, удалить старый файл (нормальный)? –

+0

@John Я думаю, мы пойдем с разумным вариантом, хотя смелый вариант не должен быть полностью отброшен. – Aillyn

+0

«Храбрый» вариант сложно реализовать. И глупая идея, потому что вы уничтожили файл в процессе его обновления. Любые проблемы, и у вас нет восстановления. Пожалуйста, не считайте смелый вариант, как даже рациональный. Если вы хотите сделать резервную копию перед тем, как попробовать «храбрый» вариант, это ** - это «нормальная» опция. –

ответ

4

Наилучшая производительность почти всегда будет получена путем написания новой версии файла, а затем с ее атомарной записью старой версии, поскольку файловые системы сильно оптимизированы для такого последовательного доступа , а также базовое оборудование (возможно, за исключением некоторых из новейших SSD с, но даже тогда это ненадежное предложение). Кроме того, это позволяет избежать разрушения данных в случае сбоя системы в любое время - у вас оставлена ​​либо старая версия файла, либо новая на своем месте. Поскольку каждая система может всегда сбой в любое время (и по закону Мерфи он выберет самый неудачный момент ;-), целостность данных обычно считается очень важной (часто данные более ценны, чем система, на которой она хранится - - следовательно, «зеркалирование» RAID-решений для обеспечения защиты от диск приводит к потере драгоценных данных ;-).

Если вы принимаете этот здравый подход, общая идея: открыть старый файл для чтения, новый для записи (создания); скопируйте N1 байт из старого файла в новый; затем пропустите N2 байта старого файла; затем скопируйте остальные; закрыть оба файла; атомически переименовать новое в старое. (У Windows, по-видимому, нет «атомарного переименования» системного вызова, используемого из Python, - чтобы сохранить целостность в этом случае, вместо атомного переименования, вы сделали бы три шага: переименуйте старый файл в резервное имя, переименуйте новый файл в старый, удалить файл с резервным именем - в случае сбоя системы во время второй из этих трех очень быстрых операций одно переименование - это все, что потребуется для восстановления целостности данных).

N1 и N2, конечно, являются двумя параметрами, указывающими, где начинается удаленная часть, и как долго это происходит. Для части об открытии файлов операторы with open('old.dat', 'rb') as oldf: и with open('NEWold.dat', 'wb') as newf:, вложенные друг в друга, явно лучше (остальная часть кода до тех пор, пока шаг переименования не будет вложен в оба из них, конечно).

Для «копировать остальные над» шаг, shutil.copyfileobj лучше (не забудьте указать длину буфера, который удобно собирается поместиться в доступной оперативной памяти, но большой один будет, как правило, дают более высокую производительность). Шаг «skip», очевидно, представляет собой только seek наоткрытый файл для чтения. Для копирования точно N1 байт из oldf в NEWF, нет прямой поддержки в стандартной библиотеке Python, так что вы должны написать свой собственный, например:

def copyN1(oldf, newf, N1, buflen=1024*1024): 
    while N1: 
     newf.write(oldf.read(min(N1, buflen))) 
     N1 -= buflen 
0

Я предлагаю memory mapping. Хотя на самом деле это , манипулируя файлом в памяти, он более эффективен, чем простое чтение всего файла в память.

Ну, вы должны так или иначе манипулировать содержимым файла в памяти, так как нет системного вызова для такой операции ни в * nix, ни в Win (по крайней мере, я не знаю).

0

Код: mmap Код файла. Это не обязательно будет сразу читать все в памяти.

Если вы действительно хотите это сделать вручную, выберите размер блока и сделайте повторное чтение и запись. Но поиски собираются убить вас ...

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