LINUX.ORG.RU

Use case для fopen mode a+

 


0

3

Добрый день.

в fopen есть режим a+, в котором можно открыть файл для чтения, но с возможностью записи в конец файла. При этом операция записи всегда устанавливает seek в конец файла.

Не могу понять почему, а главное зачем это использовать. Для чего это использовать?

Для чего это использовать?

Чтобы не поломать то, что там было до того, как ты свой шаловливый fopen туда засунул :)

Zhbert ★★★★★
()
Ответ на: комментарий от Bfgeshka

Тоже подумал про логгирование.

А ещё у майкрософтовского ворда был режим, в котором он исправленный документ пишет в несколько слоёв, сначала оригинал, потом все исправления. Со временем редактируемый таким образом документ начинает безбожно разбухать и тормозить как сволочь при загрузке, поэтому я сей режим всегда отключал. Вот похоже, что ворд чем-то похожим пользовался.

hobbit ★★★★★
()
Ответ на: комментарий от greek_31

Это джва разных примера.

На примере логирования - вместо того, чтобы держать состояние в приложении, его можно держать в логе. Например, что-то вроде «если за последний месяц было столько-то вот таких ошибок, то делай вот такое». И тогда неважно будет, произошли ошибки в одной сессии или нет, кстати.

Bfgeshka ★★★★★
()
Ответ на: комментарий от Bfgeshka

Я не совсем понял идею, но состояния тебе и так придется хранить(если ты собираешься читать из файла), т.к. каждый write устанавливает seek на конец файла. Хотя конечно всегда можно читать файл с нуля.

Если можно пример на псевдо-коде

greek_31 ★★
() автор топика
Ответ на: комментарий от greek_31

Я не совсем понял идею, но состояния тебе и так придется хранить(если ты собираешься читать из файла), т.к. каждый write устанавливает seek на конец файла. Хотя конечно всегда можно читать файл с нуля.

Не обязательно хранить всё состояние всегда. Тебе оно может быть совсем не интересно до тех пор, пока новая ошибка не возникла.

Если можно пример на псевдо-коде

Не хочу, мне лень!

Bfgeshka ★★★★★
()

Сам по себе режим append нужен для записи логов, или других файлов где не важно (совсем не важно всмысле что ты даже позицию эту выяснять не станешь), в какое место файла ты пишешь, главное что в конец. Варианты кроме логов крайне редки. Про транзакции итд не слушай, их делают по-другому.

Чтение может быть нужно если ты хочешь прочитать этот файл ещё зачем-то. Это чтение не обязательно часть того же алгоритма, который туда записывает, можно и просто для упрощения, чтобы не открывать файл два раза, использовать открывание 1 раз на две задачи.

Пример который я делал: сначала в файл записывается лог чего-то, а затем, когда это «что-то» завершилось, лог прочитывается и отправляется куда-то по сети. Описанное можно и по-другому сделать: вместо редиректа лога в файл редиректить его в pipe и читать из пайпа сразу себе в оперативную память. Но в зависимости от прочих обстоятельств выбираются разные варианты решения.

firkax ★★★★★
()

Тред не читал

Допустим, тебе надо три раза в день, в течении месяца автоматически сохранять данные с датчика температуры, записывая их.

Что лучше, просто дописывать в конец одного файла каждый раз, получая все данные в 1 месте. Или создать 90 файлов и в каждом по строчке с температурой? :)

Вот для этого и надо, тупо как ты в тетрадный лист дописываешь, а не перелистываешь каждый раз на новый лист как только вписал в текущий 1 букафку

Но оснавная цель, это не потерять ранее записанное

LINUX-ORG-RU ★★★★★
()
Последнее исправление: LINUX-ORG-RU (всего исправлений: 3)
Ответ на: комментарий от firkax

Пример который я делал: сначала в файл записывается лог чего-то, а затем, когда это «что-то» завершилось, лог прочитывается и отправляется куда-то по сети. Описанное можно и по-другому сделать: вместо редиректа лога в файл редиректить его в pipe и читать из пайпа сразу себе в оперативную память. Но в зависимости от прочих обстоятельств выбираются разные варианты решения.

Выглядит как очень странное проектирование, ну ок. Правда seek все равно дёргать надо и как следствие хранить его.

greek_31 ★★
() автор топика
Ответ на: комментарий от PeleWin

Да, также как и с r+ (тоже не удаляет).

Но как это используют? Не знаю может для форматов файлов, в которых четко заданы маркеры конца и дальше них чтение не идет. Тогда их можно перезаписывать другими данными…. Но опять же это для r+, a+ то в конец всегда писать будет.

greek_31 ★★
() автор топика
Ответ на: комментарий от firkax

Этот wal пишется не запоминая позицию в файле куда записано?

Я затрудняюсь представить зачем это было бы нужно. С огромной вероятностью (в отсутствие аварийных ситуаций) вы этот лог и читать-то обратно никогда не будете, а если уж и пришлось - вас будет волновать исключительно порядок транзакций, их completeness (пол-транзакции из лога лучше проигнорировать) и consistency (лучше все-таки иметь какую-то форму checksum - можно и мусор прочитать, по разному бывает). А вот по какому конкретному offset запись о конкретной транзакции легла в лог - да какая разница.

bugfixer ★★★★★
()

Не могу понять почему, а главное зачем это использовать. Для чего это использовать?

fgetc не вернёт EOF (ошибок/исключений) при чтении. Просто тупо будет ждать дозаписи в файл.

Помнится что в windows это не работает :-)

MKuznetsov ★★★★★
()
Ответ на: комментарий от MKuznetsov

Я что-то не слышал о такой фиче, ты уверен что оно где-то есть или хотя бы декларируется? Чтобы это реализовать, придётся либо грузить проц бесконечным циклом read() внутри, либо использовать ОС-специфичные штуки для мониторинга записи в файл (inotify,kqueue).

firkax ★★★★★
()
Ответ на: комментарий от greek_31

Если ты хочешь вперемежку делать и дозаписи и последовательное чтение - то да. Но мне такого не требовалось.

Режим «a», если что, не для того чтобы не хранить seek, а для гарантий, что никакая запись ничего не затрёт и всегда будет только в конец. Если в файл пишут два процесса, например, то без «a» они этого добиться не смогут, seek+write не атомарное и будет иногда перепутываться с соседом.

firkax ★★★★★
()

Может глупость скажу, но нам, anonymus, это позволено.

«a» — Открывает файл для добавления. Новые данные будут добавлены в конец файла. Если файл не существует, он будет создан.

«w+» — Открывает файл для чтения и записи. Если файл существует, его содержимое будет перезаписано. Если файл не существует, он будет создан.

Что делает append? - добавляет данные в имеющийся файл, не меняя системные параметры файла. Если подробней, то посмотри структуру FILE. т.е. данные записываются именно в первоначальный файл.

Что делает «w+»? по сути, создает новый файл, туда переписывает данные из старого файла и уже к ним добавляет, что ты записываешь, а старый файл удаляется. При этом системные параметры файла обновляются. т.е. данные записываются в новый файл.

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

anonymous
()
Ответ на: комментарий от firkax

Я что-то не слышал о такой фиче, ты уверен что оно где-то есть или хотя бы декларируется? Чтобы это реализовать, придётся либо грузить проц бесконечным циклом read() внутри, либо использовать ОС-специфичные штуки для мониторинга записи в файл (inotify,kqueue).

помнится что внутри винды оно как раз и грузило бесконечным частым опросом. В bsd,linux нормально - «ОС-специфичные штучки» спасают.

дубовый аналог tail -f: открыть файл a+ и всё что считывается печатать. EOF не должен быть получен пока файл вообще есть и не truncate, зато любая дозапись в файл будет считана. Вот весь смысл a+. fifo на минималках

но это было давно, сейчас на POSIX настолько все забили, что возможно уже и неправда.

MKuznetsov ★★★★★
()
Ответ на: комментарий от greek_31

И правда не читал)

Ага ) (и я снова не читал)

Открываешь в режиме a

Тогда читать записное нельзя :) Ну например

    FILE * f = fopen("text.txt","a+");
    fseek(f,0,SEEK_SET);
    printf("%c\n",(char)fgetc(f));

    fprintf(f,"hello\n");

    fseek(f,0,SEEK_SET);
    printf("%c\n",(char)fgetc(f));


    fseek(f,0,SEEK_SET);
    printf("%c\n",(char)fgetc(f));

    fprintf(f,"hello\n");

    fseek(f,0,SEEK_SET);
    printf("%c\n",(char)fgetc(f));

Несмотря на seek в начало, последующая запись всегда будет в конец. Можно использовать содержимое файла как буфер последовательных вычислений где новые записанные данные, это данные для последующих вычислений и снова записи, сикать куда хоца, а потом просто записывать, и оно будет писать всегда в конец, даже если мы сикнули в начало.

Попробуй тоже самое провернуть например с r+ получишь кашу, a не даст писать, w+ тоже всё зафаршмачит, другие записи зависят от того как ты файл seek сделал, а a+ пофигу на твои смещения в файле, оно гарантирует что ты всегда запишешь в конец, а не запутавшись со смещениями запишешь в начало. a+ Ты конечно можешь вручную, записать в файл, поставить смещение, вычитать файл, поставить смещение в конец, записать, вернуть смещение прочитать, установить смещение в конец записать. Но можно использовать просто a+ и для чтения прыгать куда хочется, а для записи просто записывать и всегда оно будет писать в конец.

LINUX-ORG-RU ★★★★★
()
Последнее исправление: LINUX-ORG-RU (всего исправлений: 1)
Ответ на: комментарий от LINUX-ORG-RU

Мне не надо объяснять поведение, я его понимаю. Мне просто интересно как это поведение использовать, желательно не в стране пони и единорогов, а что-то реальное.

greek_31 ★★
() автор топика