четене на fprintf, докато програмата работи

Така че пиша програма, която трябва да работи вечно (неща на клиентския сървър) в C, и пиша в журнал. Използвам fopen и fprintf, за да мога да пиша във файла. Проблемът ми е, че тъй като се предполага, че програмата работи вечно, наистина няма смисъл да поставя fclose. И когато Ctrl+C за спиране на процеса, и лог файла, той не показва нищо? Искам да използвам fprintf, защото ми позволява да имам форматирани низове, има ли начин да регистрирам изхода си, докато все още имам форматирани низове?


person user1289479    schedule 24.03.2012    source източник


Отговори (4)


Това, което се случва, е, че изходът се буферира и когато програмата бъде убита, буферът никога не се изхвърля на диска. Можете или периодично да изчиствате буфера (fflush), или можете да опитате да уловите сигнала за унищожаване. По-конкретно, Control + C изпраща сигнала SIGINT, така че ще трябва да регистрирате манипулатор за това.

За да минимизирам потенциалната загуба на буфер, вероятно бих използвал и двете стратегии.

Как мога да хвана събитие ctrl-c? (C++)

Редактиране: Както каза Адам, можете също така просто да отваряте и затваряте файла, когато е необходимо, но в зависимост от това колко често пишете, може да искате да запазите файла отворен, в който случай моят отговор ще се приложи.

person Corbin    schedule 24.03.2012
comment
Всъщност пиша доста често, поради което не исках да използвам метода „отваряне и затваряне всеки път“, благодаря, че ми казахте какво всъщност се случва. Ще пробвам и двата метода - person user1289479; 24.03.2012
comment
Ако просто правите периодично промиване, потенциално можете да загубите данни, ако програмата спре преди следващото промиване. Ако се опитате да уловите сигнали, тогава можете по-добре да предотвратите това и затова и двете са идеални. Ако не сте особено загрижени за производителността на IO, можете просто да ffflush след всеки запис. В зависимост от това колко агресивен е кешът на ядрото и физическия диск, fflush след всеки запис може всъщност да има много малко въздействие върху производителността. - person Corbin; 24.03.2012

Всеки път, когато искате да напишете лог съобщение, отворете файла в режим на добавяне, отпечатайте текста си в края на файла и след това го затворете.

person Adam Liss    schedule 24.03.2012

setbuf(), setvbuf() или fflush(), - и trap SIGINT или каквото и да е подходящо, свързано с вашата система.


I.e.

#include <stdio.h>
#include <unistd.h>  /* for sleep() in this example */

int main(void)
{
    FILE *fh;
    char *fn = "main.log";
    int i;

    if ((fh = fopen(fn, "w")) ==  NULL) {
        fprintf(stderr,
            "Unable to open file %s\n", fn);
        return 1;
    }

    setbuf(fh, NULL); /* Turns buffering completely off */

    for (i = 1; ; ++i) {
        fprintf(fh, "%d ok ", i);
        if (!(i%120))
            fprintf(fh, "\n");
        sleep(1);
    }

    fclose(fh);

    return 0;
}

в друга конзола:

$ tail -f main.log

Доходност: 1 добре 2 добре 3 добре 4 добре 5 добре 6 добре ^C

Или fflush(fh), когато искате да изчистите буфера за запис.

stdio.h: >


int setvbuf(FILE* stream, char* buf, int mode, size_t size);
Контролира буферирането за поточно предаване. режимът е _IOFBF за пълно буфериране, _IOLBF за буфериране на линии, _IONBF за липса на буфериране. Non-null buf указва буфер с размер размер, който да се използва; в противен случай се разпределя буфер. Връща ненула при грешка. Обаждането трябва да е преди всяка друга операция в потока.


void setbuf(FILE* stream, char* buf);
Контролира буферирането за поточно предаване. За null buf, изключва буферирането, иначе е еквивалентно на (void)setvbuf(stream, buf, _IOFBF, BUFSIZ).


int fflush(FILE* stream);
Промива потока на потока и връща нула при успех или EOF при грешка. Недефиниран ефект за входен поток. fflush(NULL) изчиства всички изходни потоци.

person Morpfh    schedule 24.03.2012

Бих се съгласил с отговора на Корбин, но вие попитахте дали има друг начин да получите форматиран изход.

Има: можете да използвате sprintf() в char буфер и след това да използвате небуфериран open/write/close I/O.

Но недей така. Продължете да използвате fopen() и co. и хванете SIGINT.

person blueshift    schedule 24.03.2012