Можно ли добавлять данные в файл без перезаписи?

Я имею дело с очень большими двоичными файлами ( от нескольких ГБ до нескольких ТБ на файл ). Эти файлы существуют в устаревшем формате и обновление требует записи заголовка в передней части файла. Я могу создать новый файл и переписать данные, но иногда это может занять много времени. Мне интересно, есть ли более быстрый способ выполнить это обновление. Платформа ограничена Linux, и я готов использовать низкоуровневые функции (ASM, C, C++) / трюки файловой системы, чтобы это произошло. В primimary библиотека Java и JNI полностью приемлема.

5 ответов


нет общего способа сделать это изначально.

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


решение может быть моделирования файловой системы: вы можете хранить ваши данные на несколько файлов, а затем предоставить некоторые функции для открытия, чтения и записи данных, как если бы это был один файл.


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

 std::string records;
 ofstream out;
std::copy( records.rbegin(), records.rend(), std::ostream_iterator<string>(out));

Это зависит от того, что вы подразумеваете под "хитрости файловой системы". Если вы хотите получить вниз-и-грязный с форматом файловой системы на диске,и размер заголовка, который вы хотите добавить, кратен размеру блока файловой системы, тогда вы можете написать программу для непосредственного управления структурами файловой системы на диске (с размонтированной файловой системой).

Это предприятие примерно так же волосато, как это звучит, хотя-это, вероятно, будет стоить того, если у вас были сотни этих гигантские файлы для обработки.


Я бы просто использовал стандартные инструменты Linux для этого.
Написание другого приложения для этого, похоже, будет неоптимальным.

cat headerFile oldFile > tmpFile && mv tmpFile oldFile

Я знаю, это старый вопрос, но я надеюсь, это поможет кому-то в будущем. Похожие на моделирования файловая система, вы можете просто использовать именованный канал:

mkfifo /path/to/file_to_be_read
{ echo "HEADER"; cat /path/to/source_file; } > /path/to/file_to_be_read

затем вы запускаете свою устаревшую программу против /path/to/file_to_be_read, и вход будет:

HEADER
contents of /path/to/source_file
...

это будет работать до тех пор, пока программа читает файл последовательно и не делает mmap() или rewind() мимо буфера.