Я чтения файла в цикле в то время как от начала до конца:прочитать файл в цикле в то время как линия за линией, а другая функция обновляет его
FILE *file;
file = fopen(path_to_file), "r");
char *line = NULL;
size_t len = 0;
while (getline(&line, &len, file) > 0) {
delete_line_from_file(line);
}
fclose(file);
Функция delete_line_from_file()
удаляет строку переданную ей из файла. Он читает весь файл через open(fd, O_RDONLY | O_CLOEXEC)
+ read()
+ close()
, затем удаляет строку из буфера и записывает весь буфер в тот же файл через open(fd, O_WRONLY | O_TRUNC | O_CLOEXEC)
+ write()
+ close()
. read()
заблокирован в контрольном замке считывания через struct flock lk
, а write()
заблокирован в виде предупреждающей блокировки записи.
Когда я читаю файл, у нас есть пропущенные строки, которые имеют какое-то отношение ко мне, когда я читаю файл от начала до конца в одном цикле во время записи на него. Если я прочитаю весь файл и прохожу через буфер по очереди, строки не будут пропущены. (Это мое предпочтительное решение до сих пор.) Также нет ошибок при усечении и записи файла. Пропущенные строки все еще находятся в файле после завершения цикла.
Могу ли я удостовериться, что мой цикл while не пропустит линию и очищает файл? Файл должен быть опущен по очереди. Он не может быть просто усечен.
Вот одно из возможных решений, которое я имел в виду. Зеркалируйте файл через fstat(file &fbuf)
и проверьте его размер с помощью if (fbuf.st_size !=0) fseek(file, 0, SEEK_SET);
, но это кажется неэффективным.
Консультационные замки являются рекомендательными. Ваш линейный цикл чтения не использует консультативную блокировку, поэтому он может читать файл во время обновлений. Все стороны, как читатели, так и писатели, должны блокировать блокировку, чтобы повлиять на них. Было бы проще использовать блокировки и белые записи (перезапись содержимого с игнорируемыми данными, такими как пробелы или нули), поэтому длительность блокировки была бы короткой; и только изредка делайте «переупаковку», удаляя все белые. Для удаления строки достаточно зафиксировать и переписать содержимое файла до конца файла, а затем усечь. –
Последняя часть «Для удаления строки достаточно зафиксировать и переписать содержимое файла до конца файла, а затем усечь». Я пока не совсем понимаю. Возможно, это то, чего вы не предполагали, потому что я не указал этого в моем вопросе: что, если бы я должен был удалить строку из середины файла? –
Если ваше содержимое файла 'ABCDE', и вы удаляете' C', вам не нужно читать и переписывать весь файл; вы можете просто начать чтение с начала 'D' до конца файла и писать начинать с начала' C', а когда вы достигнете конца, обрезайте файл до той длины, в которой закончилась окончательная запись. Во время этого вам потребуется блокировка исключительной записи/записи в файле (по крайней мере, с начала 'C' до конца файла).Если ваш линейный читатель берет блокировку чтения в файле, вне цикла, он всегда получает согласованное представление. Другие стратегии возможны, но сложнее. –