Это немного сложно сделать, потому что модель файлов C, унаследованная от Unix (они были в основном написаны с помощью кода), на самом деле не определяет файл как список строк. Вместо этого он определяет строку как строку байтов, оканчивающуюся новой строкой, а файл (грубо говоря) - как сохраненную строку байтов потенциально ограниченной длины, где вы можете пропустить различные части. Это значительно расплывчато, но терпите меня.
Когда проблема становится понятнее, когда мы пытаемся перевести наши идеи - «изменить эту строку», «удалить эту строку» - в файловые операции. Мы можем прочитать строку, просто остановившись на новой строке, но просто нет команды разрезать ее на разделы; только для установки конца (ftruncate ()). Таким образом, чтобы изменить размер строки, нам нужно скопировать все данные, которые следуют за ней. Это можно сделать, но очень часто проще просто создать файл заново. Сравните тонкости реализации memmove ().
Традиционный метод для этого существует в двух вариантах, в зависимости от того, какие побочные эффекты вы можете терпеть.
Один из них - записать обновленную версию в другой файл, а затем переименовать () на место. Преимущество этого заключается в том, что новый файл будет готов к тому времени, когда вы его поместите, но есть и недостатки, что он может не соответствовать старому файлу точно в том, что касается разрешений и т. Д., И он не будет виден другим программам, которые уже был открыт старый. Если две программы изменяют файл следующим образом, это условие гонки, поскольку одно из изменений перезаписывается другим.
Другой способ - полностью загрузить данные и записать измененную версию на место. Это означает, что сам файл остается на месте, у него есть права доступа и все остальное, но вы сохраните время, пока он сохранит, что это смесь старого и нового содержимого. Текстовые редакторы, как правило, делают это, часто сохраняя старое содержимое в виде отдельного файла на случай, если что-то пойдет не так.
Существуют также инструменты для управления побочными эффектами, такие как файловые системы с поддержкой версий, блокировка файлов и даже библиотеки, подготовленные для параллельных изменений (на ум приходит метакит). Большую часть времени мы будем использовать инструменты, которые уже есть, такие как sed -i.