Сжатие файла в C

Как сжать файл в C? Например, если я открою файл размером 2 МБ, сделаю некоторую работу и решу, что все еще должен существовать только 1 МБ файла, как это сделать? Я знаю, как использовать write( fd,....) для записи в файл, но что, если я хочу вырезать определенные части в середине файла или обрезать его?

7 ответов

Решение

Вы, вероятно, ищете truncate()ftruncate() или на окнах, SetEndOfFile(), Нет способа "вырезать" кусок файла, вам нужно будет переписать его спереди, а затем обрезать.

Практически в каждой реальной системе есть какой-то способ усечения файла, но стандарт C не предоставляет его в стандартной библиотеке.

Это означает, что почти все, что вы можете сделать, это определить функцию для выполнения работы и реализовать эту функцию для каждой цели, которая вас волнует (например, в Windows это вызовет SetEndOfFileв Unix-подобных системах ftruncate, так далее.).

Изменить: просто чтобы уточнить: это работает только для "или усечь его" часть вопроса. Большинство файловых систем не предоставляют ничего, чтобы "вырезать определенные части в середине файла". Если вы хотите удалить что-то из середины файла, вам, как правило, нужно переписать весь файл или обрабатывать вещи самостоятельно. Последний обычно работает с некоторой структурой, похожей на базу данных, где на самом деле не удаляются данные из середины файла; вместо этого вы создаете что-то вроде индекса, который сообщает о расположении данных, которые вас интересуют, и просто помечает детали, которые больше не используются, когда вы их удаляете. Эти части могут быть использованы повторно, если / если вы добавите данные позже. В некоторых случаях у вас будет функция "сжатия", которая берет такую ​​базу данных и перезаписывает ее, чтобы устранить мертвое пространство (но снова вы снова переписываете файл).

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

Моя точка зрения заключается в том, что нет прямого способа просто удалить некоторую часть файла посередине.

Если вы хотите сохранить предыдущее содержимое файла до некоторой длины (длина больше нуля), тогда POSIX предоставляет функции truncate() и ftruncate() для задания.

#include <unistd.h>
int ftruncate(int fildes, off_t length);
int truncate(const char *path, off_t length);

Название указывает на основную цель - сокращение файла. Но если указанная длина больше, чем предыдущая, файл увеличивается (заполнение нулями) до нового размера. Обратите внимание, что ftruncate() работает с файловым дескриптором, а не с FILE *; Вы могли бы использовать:

if (ftruncate(fileno(fp), new_length) != 0)...обработка ошибок...

Впрочем, вполне вероятно, что для ваших целей урезание в open - это все, что вам нужно.

У вас есть два варианта:

  1. Создайте временный файл, запишите в него нужное содержимое и переименуйте его в исходный файл.
  2. Прочитайте весь файл в память, отредактируйте в памяти и используйте freopen, чтобы открыть файл, обрезая его

Если у вас есть система POSIX, взгляните на ftruncate(),

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

Другие вопросы по тегам