2015-08-22 3 views
2

Я чтения файла в цикле в то время как от начала до конца:прочитать файл в цикле в то время как линия за линией, а другая функция обновляет его

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);, но это кажется неэффективным.

+0

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

+0

Последняя часть «Для удаления строки достаточно зафиксировать и переписать содержимое файла до конца файла, а затем усечь». Я пока не совсем понимаю. Возможно, это то, чего вы не предполагали, потому что я не указал этого в моем вопросе: что, если бы я должен был удалить строку из середины файла? –

+0

Если ваше содержимое файла 'ABCDE', и вы удаляете' C', вам не нужно читать и переписывать весь файл; вы можете просто начать чтение с начала 'D' до конца файла и писать начинать с начала' C', а когда вы достигнете конца, обрезайте файл до той длины, в которой закончилась окончательная запись. Во время этого вам потребуется блокировка исключительной записи/записи в файле (по крайней мере, с начала 'C' до конца файла).Если ваш линейный читатель берет блокировку чтения в файле, вне цикла, он всегда получает согласованное представление. Другие стратегии возможны, но сложнее. –

ответ

0

Итак, цель состоит в том, чтобы полностью удалить файл?

Почему бы вам не открыть файл, например:

open("file", O_TRUNC | O_WRONLY);

Это позволит открыть файл с усечением. С другой стороны, и, возможно, лучшее решение, вы можете сделать это:

fopen("file", "w"); 

Еореп с «ш» вариант удалить исходный файл и заменить его на новый файл имя файла «».

+0

Файл должен быть удален последовательно. –

0

Используйте fseek и ftell внутри вашей петли.

Два процесса, изменяющих один и тот же файл, являются рецептом проблем. Возможно, вам нужно использовать трубу (2).