"r", "w", "a", etc., as in the
example:
FILE *ftext = fopen(fname, "r");On the other hand, binary files are opened using one of the modes
"rb", "wb", "ab", etc.
FILE *fbin = fopen(fname, "rb");On non-Unix systems, like DOS, OS/2 and Windows, text files are treated differently than binary files, and the use of the
'b'
code letter is essential. Unfortunately, Standard C provides no way
to change the mode on standard I/O
(stdin, stdout, stderr).
This is necessary when handling binary files in a pipeline; e.g.
echo Hello | gzip -c > hello.gz
#define STDIN 0
#define STDOUT 1
#define STDERR 2
#ifdef _WIN32
# include <io.h>
# include <fcntl.h>
# define SET_BINARY_MODE(handle) setmode(handle, O_BINARY)
#else
# define SET_BINARY_MODE(handle) ((void)0)
#endif
Before performing any other operation on the stream that is supposed to
handle binary data, invoke the SET_BINARY_MODE macro.
For example:
/* Prepare the standard output for writing binary data. */
/* This must be done before writing anything to stdout. */
SET_BINARY_MODE(STDOUT);
The vanilla definition of SET_BINARY_MODE allows the code
to be successfully compiled and executed on Unix. However, the problem
remains on other (non-Windows && non-Unix) systems.
"sysconf.h" header file provides the
information necessary for the definition of
SET_BINARY_MODE.
#include "sysconf.h"
#ifdef HAVE_SETMODE
# define SET_BINARY_MODE(handle) setmode(handle, O_BINARY)
#else
# define SET_BINARY_MODE(handle) ((void)0)
#endif
Download: sysconf.h
If you are using "sysconf.h", you can also rely on
HAVE_ISATTY to detect the presence of
isatty().
Writing binary data to non-redirected output results in displaying
meaningless symbols on the screen; this happens frequently in older
Unix programs, and it is highly unelegant from the user's point of view.
Reading any kind of data from non-redirected input results in the
program waiting for the user to type the input, although the user
doesn't know what to do, except to press Ctrl+C.
isatty() is a function that returns TRUE
if the handle is associated with a TTY (e.g. keyboard, screen, printer,
serial port), and FALSE in the other circumstances
(e.g. the handle is associated with a regular file, or is a part of
a pipeline). For example, if the standard output is redirected to
a file, or piped to another program, then isatty(STDOUT)
returns FALSE.
If a command-line program is waiting for data from the standard input,
and the user is not supposed to type it, then it would be nice
to check for isatty() first:
#ifdef HAVE_ISATTY
if (isatty(STDIN))
{
fprintf(stderr, "** Error: missing input\n");
fprintf(stderr, help_message);
exit(EXIT_FAILURE);
}
#endif
Similarly, if the program is supposed to write binary data to the
standard output:
#ifdef HAVE_ISATTY
if (isatty(STDOUT))
{
fprintf(stderr, "** Error: can't write binary data\n");
fprintf(stderr, help_message);
exit(EXIT_FAILURE);
}
#endif
Note: isatty() needs not be checked more than once.