File I/O Part 2

  1. Writing to an output file
    1. Include fstream library
    2. Use ofstream class
    3. Example writing out a string to a file
      ofstream fout;
      
      // Create a new file
      fout.open("test.txt");
      
      // Send output to the file
      fout << "This is a test." << endl;
      
      // Flush the output buffer
      fout.close();
      
      would produce a file called test.txt (in the same directory as your .cpp file) that contains:
      This is a test.
      
    4. Important methods
      1. open("filename") - creates a new file if it doesn't exist or erases contents of previously existing file
      2. fout << - send output to the file instead of to the console (cout)
      3. close() - flush the output buffer (output buffer might contain data that has not been written to the file yet)
  2. Appending to a file
    1. Instead of erasing an output file's content, it can be helpful to keep the existing contents and add stuff to the end of it
    2. Use ios::app flag when openning to append to a file
    3. This example will append a single line to test.txt
      ofstream fout;
      fout.open("test.txt", ios::app);
      fout << "This line will be appended to the end of the file.";
      fout.close();
      
      would produce:
      This is a test.
      This line will be appended to the end of the file.
      
  3. Combining use of input and output files
    1. This example copies the contents of an existing file to a new file
      string input_filename, output_filename, line;
      
      cout << "Input filename? ";
      getline(cin, input_filename);
      
      output_filename = "Copy - " + input_filename;
      
      ifstream fin;
      fin.open(input_filename);
      
      ofstream fout;
      fout.open(output_filename);
      
      // Read each line from the input file and send it to
      // the output file
      getline(fin, line);
      while (fin.good())
      {
      	fout << line << endl;
      	getline(fin, line);
      }
      
      fin.close();
      fout.close();
      
      cout << "Copied the file to " << output_filename;
      
      Running the program:
      Input filename? nums.txt
      Copied the file to Copy - nums.txt
      
    2. Problem 1: What if the input file doesn't exist? Use fail() to fix this
    3. Problem 2: What if we want to guard against over-writing an existing output file? First open the file for input and use fail() to see if the file exists or not
  4. File buffers
    1. Data from files do not go directly to and from files
    2. It is much faster and efficient to read large chunks of data (several KB) into memory or write large chunks out to file rather than read/write character by character
    3. Input file buffer - RAM used to hold the contents of an input file
      1. Opening the file creates the input file buffer, and a read operation transfers the first large chunk of data from the file into the buffer
      2. Reading from the file actually moves data from the buffer into your variable
      3. When the buffer is empty, another read operation transfers a large chunk of data from the file into the buffer
    4. Output file buffer - RAM used to hold the data to be written to an output file
      1. Opening the file creates an output file buffer which is initially empty
      2. Writing to the file sends the data to the buffer
      3. When the buffer is full, the contents are dumped out to the file, and the buffer is emptied
      4. Closing the file flushes any data still remaining in the buffer out to the file
  5. Passing streams to functions
    1. ofstream and ifstream objects may be passed to functions as parameters
    2. They must be passed by reference, or logic errors will result
    3. Example:
      // Must pass streams by reference!
      int ReadNumber(ifstream &fin)
      {
      	int num;
      	fin >> num;
      	return num;
      }
      
      void main()
      {
      	ifstream fin;
      	fin.open("somefile.txt");
      
      	// Display number from somefile.txt
      	cout << ReadNumber(fin);
      
      	fin.close();
      }