File I/O

Goals

By the end of this lab you should:

Introduction

Reading and writing to and from a file is often referred to as "File I/O" where the I stands for "input" and the O stands for "output". In this lab you will learn the basics of reading and writing from and to a file in C++.

The "Everything is a File" Paradigm

In linux, in addition to standard files, almost everything is treated as if it were a file. The cd-rom is a file, a usb thumb drive is a file, the hard disk is a file, etc. If this seems a bit weird to you, consider what all of these things are referred to when you go shopping for them ... Media. This is because they are all things which can be read from or written too. In the linux operating system, a file is something that can be read from or written too. Employing this abstraction makes writing programs which use these devices much easier. The programmer has a single interface for writing to a file. It doesn't matter whether that file is the cd-rom, or a file called "my_numbers.txt"; the interface for writing to both are the same. In this class we won't go into how to write to devices such as the cd-rom, however it's helpfull to understand this paradigm when approaching the topic of file I/O.

Files You've Already Been Using

You may not have realized it, but you've already been reading and writing to and from files. "How?" you ask...standard input ( the keyboard ) and standard output ( the terminal ) are actually files in linux. When you sharp include iostream files are opened with the names cin and cout that you can use to read from write to the files corresponding to standard input and standard output.

Opening Your Own Files

Since you already know how to read from and write to a file ( ie. just like using cin and cout ) all you really need to know is how to open a file yourself.

In order for you to open your own files you need to sharp include the header fstream. This will allow you to use the types ifstream and ofstream. To open a file for reading you want to create an ifstream object. To open a file for writing you want to create on ofstream object. So to write the something to a file you might do the following.

#include <fstream>

int main()
{
  // Open a file for writing
  std::ofstream outfile( "afile.txt", std::ios::out );

  // Write to the file
  outfile << "I just wrote to a file!" << std::endl;

  // Close the file
  outfile.close();

  return;
}
    

The parameters to the constructor are the name of the file ( includeing path if necessary ) and a series of flags bitwise or'd together. The second parameter is optional and is likely not necessary for this class; however its good to know that its an option.

You can also declare the ifstream/ofstream and then open the file using the member function open as in the next snippet of code:

#include <fstream>

int main()
{
  // Open a file for reading
  std::ifstream infile;
  infile.open( "afile.txt" );

  // Read in a double from the file 
  double num_from_file;
  infile >> num_from_file;

  // Close the file
  infile.close();

  return;
}
    

Also, notice that in order to write things you use the insertion operator ( << ) and to read things you use the extraction operator ( >> ) just like when you use the streams cin and cout.

Verifying That the File Was Opened

Sometimes opening the file will fail. This could be for a variety of reasons, but the most common is that the file doesn't exist ( when opening a file for reading ) or the name of the file has been misspelled. You surely don't want to attempt to read and write from the file if it hasn't been opened. To test if a file has been successfully opened you simply test its truth value. If it evaluates as true, the file has been opened correctly. If it evaluates as false, it was not. For example:

#include <fstream>

int main()
{
  // Open a file for input
  std::ifstream num_file( "numbers.txt", std::ios::in );

  // Test to see if the file opened correctly
  if ( not num_file )
  {
    std::cout << "Could not open the file numbers.txt" << std::endl;
  }
}