File I/O using cstdio

Often we want our programs to write data into files (rather than onto the screen) or to read data from a file (rather than the keyboard).

To do this, instead of using printf for output, we will use fprintf (i.e. file printf) and instead of using scanf for input, we will use fscanf (i.e. file scanf).

Calls to these functions will look very similar to the way we already use printf and scanf, but with one extra parameter controlling the file we are reading from or writing to.

The extra parameter that controls access to a file is called a file pointer, as it points to our current location in a file as we read our way through it or write content into it.

The general sequence we follow whenever we work on a file is as follows:

  1. Try to open the file: here we specify the name of the file and how we want to use it: read from, write to, or append. Writing to overwrites the previous content of the file (if any), whereas append adds new content to the end of the existing file.

  2. Check if the file opened successfully or not (we cannot read from a file that doesn't exist, and we cannot use a file if our account doesn't have the appropriate permissions to use that file).

  3. If it did open successfully, perform all the reads and writes we want (discussed later).

  4. Once we are finished all our reads or writes for that file, close it.

The C++ syntax for these steps is as follows:


File pointers as parameters

Sometimes we want to open a file pointer in one function, pass it as a parameter to another function, and have the called function read/write contents.

To do this, we must make sure the file pointer is passed-by-reference, and it is a good idea for the function to test the file pointer it receives to ensure it really is open, e.g.
#include <cstdio>

// function to write an integer value into a file,
// the file should have been opened for output earlier
void writeNumberIntoFile(FILE* fp, int N);

int main()
{
     // attempt to open a file for writing
     FILE* fpout = fopen("somefile", "w");
     if (fpout == NULL) {
        printf("Could not open file\n");
     } else {
        // get the function to write value 123 into the file
        writeNumberIntoFile(fpout, 123);

        // close the file when we're done
        fclose(fpout);
     }
     return 0;
}

// function to write an integer value into a file,
// the file should have been opened for output earlier
void writeNumberIntoFile(FILE* fp, int N)
{
   if (fp != NULL) {
      fprintf(fp, "%d\n", N);
   }
}


Binary I/O

Everything above assumes plain text files are being processed, but sometimes we want to manipulate binary files (images, executables, etc).

To do so, we use binary mode, adding the letter b to our chosen mode, e.g. "rb", "rb+", "wb", etc.

We can then write binary variable contents directly into the file or read the file contents directly into variables (assuming we know the layout of the file content).

To read from the file, we specfiy where to put the data being read, how big each data element is, how many data elements there are, and the file pointer to read from, e.g. assuming i is an int:
fread(&i, sizeof(int), 1, fp);

Similarly, to write variable contents into the file we use fwrite:
fwrite(i, sizeof(int), 1, fp);