File I/O

In the programs we’ve written so far:

The abstraction for both input and output is a stream of characters:

C uses the same abstraction, streams of characters, for input from files and output to files.

File handles, opening and closing files

Before you can read from or write to a file, you need to open the file.  To open a file, use the fopen function.

fopen( filename, mode )

The filename is a character string indicating the name of the file to open.

The mode is a string indicating how the file should be opened:

Examples of modes:

Mode string Meaning
"r" open for reading text
"w" open for writing text
"a" open for writing, append to existing contents
"r+" open for both reading and writing text
"w+" open for both reading and writing text: file is created if it doesn’t exist
"rb" open for reading binary data
"wb" open for writing binary data

We won’t be discussing binary I/O.

The result (return value) of calling the fopen function is a file handle.  You can think of a file handle as a special value which refers to the open file.  (If you think of the file as a briefcase, then the file handle is the handle that allows you to pick up the briefcase and access its contents.)

You will want to store the file handle in a variable.  The type of a file handle is FILE *. You can read this type as “pointer to file”.

You will need to check the file handle returned by fopen to see if the file was actually opened.  You can treat the file handle value as though it were a boolean value: it will be true if the file was opened, or false if the file could not be opened.  E.g.:

FILE *in = fopen("myfile.txt", "r");
if (!in) {
    fprintf(stderr, "Couldn't open the input file\n");
    exit(1);
}

After you are done reading from or writing to a file, the program should close the file:

fclose( filehandle )

So, a program that reads text data from a file might look like this:

FILE *in = fopen("myFile.txt", "r");
if (!in) {
    fprintf(stderr, "Couldn't open the input file\n");
    exit(1);
}

// code that reads from the file

fclose(in);

File I/O functions

The good news about reading from and writing to files is that the functions you can use functions that are equivalent to printf, scanf, etc.  The only thing that’s different is that you’ll need to pass the file handle as an argument.

Output to a file:

fprintf( file handle, format string, list of values )

Formatted input from a file:

fscanf( file handle, format string, list of variables )

Read the next character from a file and return its code (returning a negative value if no more characters):

fgetc( file handle )

So, fprintf is like printf, fscanf is like scanf, and fgetc is like getchar.

The feof function takes an input file handle as its argument, returns true if the file is known to be at end-of-file, false otherwise:

feof( file handle )

Standard handles

The standard handles are file handles that automatically exist when your program starts.  You don’t need to open them explicitly:

You have used the standard handles in every program so far:

Complete example

Count the number of occurrences of the letter Q in a file:

FILE *in;
int ch, count;

count = 0;

in = fopen("pandp.txt", "r");
if (!in) {
    fprintf(stderr, "Couldn't open input file\n");
    exit(1);
}

while (!feof(in)) {
    ch = fgetc(in);
    if (ch == 'Q') {
        count++;
    }
}

printf("There were %i occurrences of 'Q'\n", count);

fclose(in);