16.2: Opening and Closing Files (fopen, fclose, etc.)

As mentioned, the fopen function opens a file (or perhaps some other I/O object, if the operating system permits devices to be treated as if they were files) and returns a stream (FILE *) to be used with later I/O calls. fopen's prototype is

	FILE *fopen(char *filename, char *mode)
For the rest of this chapter, we'll often use prototype notations like these to describe functions, since a prototype gives us just the information we need about a function: its name, its return type, and the types of its arguments (perhaps along with identifying names for the arguments).

fopen's prototype tells us that it returns a FILE *, as we expect, and that it takes two arguments, both of type char * (i.e. ``string''). The first string is the file name, which can be any string (simple filename or complicated pathname) which is acceptable to the underlying operating system. The second string is the mode in which the file should be opened. The simple mode arguments are

You can also tack two optional modifier characters onto the mode string: Modes "r+" and "w+" let you read and write to the file. You can't read and write at the same time; between stints of reading and stints of writing you must explicitly reposition the read/write indicator (see section 16.9 below).

``Binary'' or "b" mode means that no translations are done by the stdio library when reading or writing the file. Normally, the newline character \n is translated to and from some operating system dependent end-of-line representation (LF on Unix, CR on the Macintosh, CRLF on MS-DOS, or an end-of-record mark on record-oriented operating systems). On MS-DOS systems, without binary mode, a control-Z character in a file is treated as an end-of-file indication; neither the control-Z nor any characters following it will be seen by a program reading the file. In binary mode, on the other hand, characters are read and written verbatim; newline characters (and, in MS-DOS, control-Z characters) are not treated specially. You need to use binary mode when what you're reading and writing is arbitrary byte values which are not to be interpreted as text characters.

Of course, it's possible to use both optional modes: "r+b", "w+b", etc. (For maximum portability, it's preferable to put + before b in these cases.)

If, for any reason, fopen can't open the requested file in the requested mode, it returns a null pointer (NULL). Whenever you call fopen, you must check that the returned file pointer is not null before attempting to use the pointer for any I/O.

Most operating systems let you keep only a limited number of files open at a time. Also, many versions of the stdio library allocate only a limited number of FILE structures for fopen to return pointers to. Therefore, if a program opens many files in sequence, it's important for it to close them as it finishes with them. Closing a file fp simply requires calling fclose(fp). (Any open streams are automatically closed when the program exits normally.)

The standard I/O library normally buffers characters--that is, when you're writing, it saves up a chunk of characters and then writes them to the actual file all at once; and when you're reading, it reads a chunk of characters from the file all at once and them parcels them out to the program one at a time (or as many characters at a time as the program asks for). The reasons for buffering have to do with efficiency--the calls to the underlying operating system which request it to read and write files may be inefficient if called once for each character or each few characters, and may be much more efficient if they're always called for large blocks of characters. Normally, buffering is transparent to your program, but occasionally it's necessary to ensure that some characters have actually been written. (One example is when you've printed a prompt to the standard output, and you want to be sure that it's actually been written to the screen.) In these cases, you can call fflush(fp), which flushes a stream's buffered output to the underlying file (or screen, or other device). Naturally, the library automatically flushes output when you call fclose on a stream, and also when your program exits.

(fflush is only defined for output streams. There is no standard way to discard unread, buffered input.)

Read sequentially: prev next up top

This page by Steve Summit // Copyright 1996-1999 // mail feedback