问题
I want to implement logging functionality in C and log messages to both stdout and some file. I would like to write something like fprintf(logout, "msg"); with somehow declared FILE* logout which will redirect strings to both stdout and some file. Is it possible?
回答1:
You apparently want a FILE
-like object that redirects its writes to two underlying FILE
s (stdout
and the log file). Standard C doesn't allow "subclassing" FILE
objects in any way, so this is not possible in C. However, GNU libc does, so if your program is Linux-only, you can do that with some programming. As this is extremely non-portable, it is strongly recommended against.
A more portable way to achieve this is by writing to a pipe and creating a process or thread that reads from the pipe and writes to both underlying files. For example, assuming POSIX:
FILE *tee_file(FILE *fp1, FILE *fp2)
{
int fds[2];
if (pipe(fds))
return NULL;
switch (fork()) {
case 0: {
char buf[512];
int nread;
FILE *r = fdopen(fds[0], "r");
close(fds[1]);
while ((nread = fread(buf, 1, sizeof buf, r)) {
fwrite(buf, 1, nread, fp1);
fwrite(buf, 1, nread, fp2);
}
_exit(0);
}
case -1:
return NULL;
}
close(fds[0]);
return fdopen(fds[1], "w");
}
/* after calling "fp = tee_file(fp1, fp2)", writes to fp
end up in fp1 and fp2. */
Both approach add a good deal of complication to your program which should be justified by a very good reason. What you want is to use a logging framework that allows writing to multiple outputs (they all do), or write your own as outlined by H2CO3's answer.
回答2:
If this is on Linux, you can open a pipe to the tee
command:
FILE *logout = popen("tee logfile", "w");
回答3:
Why don't you make your very own logging function?
int log_fprintf(FILE *stream, const char *restrict fmt, ...)
{
va_list args;
va_start(args, fmt);
vfprintf(stream, fmt, args);
va_end(args);
va_start(args, fmt);
int n = vfprintf(stdout, fmt, args);
// conceptually, rather `stderr`, please!
va_end(args);
return n;
}
来源:https://stackoverflow.com/questions/15716636/writing-to-two-file-descriptors-by-only-one-operation