Така че пиша програма, която трябва да работи вечно (неща на клиентския сървър) в C, и пиша в журнал. Използвам fopen
и fprintf
, за да мога да пиша във файла. Проблемът ми е, че тъй като се предполага, че програмата работи вечно, наистина няма смисъл да поставя fclose
. И когато Ctrl+C за спиране на процеса, и лог файла, той не показва нищо? Искам да използвам fprintf
, защото ми позволява да имам форматирани низове, има ли начин да регистрирам изхода си, докато все още имам форматирани низове?
четене на fprintf, докато програмата работи
Отговори (4)
Това, което се случва, е, че изходът се буферира и когато програмата бъде убита, буферът никога не се изхвърля на диска. Можете или периодично да изчиствате буфера (fflush), или можете да опитате да уловите сигнала за унищожаване. По-конкретно, Control + C изпраща сигнала SIGINT, така че ще трябва да регистрирате манипулатор за това.
За да минимизирам потенциалната загуба на буфер, вероятно бих използвал и двете стратегии.
Как мога да хвана събитие ctrl-c? (C++)
Редактиране: Както каза Адам, можете също така просто да отваряте и затваряте файла, когато е необходимо, но в зависимост от това колко често пишете, може да искате да запазите файла отворен, в който случай моят отговор ще се приложи.
Всеки път, когато искате да напишете лог съобщение, отворете файла в режим на добавяне, отпечатайте текста си в края на файла и след това го затворете.
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) изчиства всички изходни потоци.
Бих се съгласил с отговора на Корбин, но вие попитахте дали има друг начин да получите форматиран изход.
Има: можете да използвате sprintf() в char буфер и след това да използвате небуфериран open/write/close
I/O.
Но недей така. Продължете да използвате fopen() и co. и хванете SIGINT.