Reputation:
Is it possible for a caller program in C to know how many bytes it has printed to a file stream such as stdout
without actually counting and adding up the return values of printf
?
I am trying to implement control of the quantity of output of a C program which uses libraries to print, but the libraries don't report the amount of data they have printed out.
I am interested in either a general solution or a Unix-specific one.
Upvotes: 3
Views: 1598
Reputation: 14696
No idea how reliable this is, but you can use ftell
on stdout:
long int start = ftell(stdout);
printf("abcdef\n");
printf("%ld\n", ftell(stdout) - start); // >> 7
EDIT Checked this on Ubuntu Precise: it does not work if the output goes to the console, but does work if it is redirected to a file.
$ ./a.out
abcdef
0
$ ./a.out >tt
$ cat tt
abcdef
7
$ echo `./a.out`
abcdef 0
$ echo `cat tt`
abcdef 7
Upvotes: 0
Reputation: 28000
It's rather a heavyweight solution, but the following will work:
pipe()
stdout
to the write-side of the pipe, and close the read side (and the old stdout
)stdout
(which is the original stdout
) - counting it as it goes paststdout
(which is now the pipe) as usualBasically the idea is to spawn a child process, and pipe all output through it, and have the child process count all the data as it goes through.
The precise form of IPC to use may vary - for example, shared memory (with atomic reads/writes on each side) would work well for fast transfer of data, but other methods (such as sockets, more pipes etc) are possible, and offer better scope for synchronisation.
The trickiest part is the synchronisation, i.e. ensuring that, at the time the child tells the parent how much data has been written, it has already processed all the data that the parent said (and there is none left in the pipe, for example). How important this is will depend on exactly what your aim is - if an approximate indication is all that's required, then you may be able to get away with using shared memory for IPC and not performing any explicit synchronisation; if the total is only required at the end then you can close stdout
from the parent, and have the child indicate in the shared memory when it has received the eof
notification.
If you require more frequent readouts, which must be exact, then something more copmlex will be required, but this can be achieved by designing some sort of protocol using sockets, pipes, or even condvars/semaphores/etc in the shared memory.
Upvotes: 0
Reputation: 16406
POSIX-specific: redirect stdout
to a file, flush after all writing is done, then stat the file and look at st_size
(or use the ls
command).
Update: You say you're trying to control the quantity of output of a program. The POSIX head
command will do that. If that's not satisfactory, then state your requirements clearly.
Upvotes: 1