Удаление строки из файла на языке C
Я хочу удалить определенные строки в файле и вставить некоторые строки в один и тот же файл на основе того, соответствуют ли определенные части строки указанной строке. Есть ли способ сделать это без использования временного файла для копирования содержимого и т.д.?
Ответы
Ответ 1
Проблема заключается в том, что файл (по существу) представляет собой массив байтов на диске (или любой другой физический субстрат, но, в любом случае, байты!), а "строка" может принимать различное количество байтов; поэтому, чтобы вставлять или удалять строки (если вы не выполняете строгую замену строки другой строкой точно такой же длины в байтах), потребуется "переместить" весь остальной файл "вверх" или "вниз" на разницу в байтах... что может быть чрезвычайно тяжелой операцией (так как остальная часть файла может быть гигабайтом, даже если вы просто меняете одну длину строки на 1 байт в начале файла).
Таким образом, такие операции могут быть невероятно обременительными и, как правило, никогда не предлагаются в качестве примитивов в ЛЮБОЙ язык, поддерживающий файлы с переменной длиной строки (C, Python, Java, С++, Ruby или любой другой такой язык). Крайне маловероятно, что вам действительно нужно заплатить такую потенциально несвязавшуюся стоимость в производительности и риске (системная или дисковая авария во время "сдвига" GB или данных вверх или вниз может привести к уничтожению универсальности вашего всего огромного файла), когда совершенно простая, адекватная, быстрая, безопасная и разумная техника, которую вы пытаетесь избежать, имеет в основном нулевые сокращения (так что это далеко не очевидно, ПОЧЕМУ вы пытаетесь избежать этого?).
Используйте результирующий файл, отличный от исходного файла, когда выполняется mv файл результата по исходному файлу (атомная операция в большинстве систем, если вы находитесь в одной и той же файловой системе), и у вас действительно есть лучший из всех возможных миров.
Ответ 2
Вы не можете легко "вырезать" часть файла на месте. Вы всегда делаете временную копию где-то. Это не C-вещь; это верно для любого языка.
Вы можете mmap файл, а затем, когда вы найдете строку, которую хотите стереть, вы можете memcpy все после нее расположение начала линии. Я бы спросил, насколько это будет эффективно; временный файл может быть быстрее.
Ответ 3
Если файл недостаточно велик для обработки в ОЗУ, вы можете использовать Связанный список строк, где каждая node представляет Линию, то есть node связанного списка создается на основе '\n ', а затем вы можете выполнить операции вставки и удалить операции в связанном списке по мере необходимости, а затем вы можете перезаписать в том же файле, используя связанный список.
Например, mytext.txt
Это тестовый файл
Строка должна быть добавлена выше
Эта строка должна быть удалена
Теперь, когда вы создаете связанный список вышеуказанного файла, это будет выглядеть как
[Это тестовый файл] → [Строка должна быть добавлена выше] → [Эта строка должна быть удалена] → [NULL]
Вставка Операция изменит связанный список на
[Это тестовый файл] → [Это новая строка] → [Строка должна быть добавлена выше] → [Эта строка должна быть удалена] → [NULL]
Операция удаления изменит связанный список на
[Это тестовый файл] → [Это новая строка] → [Строка должна быть добавлена выше] → [NULL]
Теперь вы можете записать связанный список в файл mytext.txt с символом "\n" в конце каждого node.
Заключительный файл будет, mytext.txt
Это тестовый файл
Это новая строка
Строка должна быть добавлена выше