Windows vs. Linux.
As often, we would write our code in a portable way and just create a simple while loop likewhile(!feof(stdin)) { size_t bytes = fread(bufferInput, 1, m_blocksize, stdin); // .... }
but here you are face to a piece of code dependent of the platform you target, let me explain.
- On Linux stdin and stdout are by default open using the binary mode.
- On the other side on Windows they will be open using the text mode.
because of that, the feof and all the fread, fgets function can have different output on the 2 systems. For example, on Windows, reading using the normal mode will convert
\r\n
(Windows newline) to the single character ASCII 10, instead of returning 2 bytes under Linux !To avoid that pitfall, you can use 2 approach:
- freopen, portable and easy to put before using stdin
- or _setmode/setmode available under Windows and also Linux/GCC under certain condition.
freopen:
Basically, the best thing you should do is this:
freopen(NULL, "rb", stdin);
This will reopen stdin using the binary mode, so under Linux it will change nothing, and on Windows,
it will avoid abnormal character interpretation (premature end-of-stream, etc…). But take care of the
compiler you use because depending of the freopen spec you read the behavior when passing path
equal to NULL may be different... see the 2 following description:
setmode:
That method is less portable and may require some addition to your GCC environment.
With VS for example, you can call _setmode (require fcntl.h and io.h)
_setmode(_fileno(stdin), _O_BINARY);
_setmode(_fileno(stdout), _O_BINARY);
But under linux, the setmode isn’t a standard lib function, it’s a libbsd function. So you have to include
<bsd/unistd.h> and link with –lbsd.
Conclusion
If you have to write a multi-platform command line tool using stdin/stdout the most portable way to do it is the freopen solution!