Programming in C++

File I/O

Gerald Senarclens de Grancy

Purpose of File I/O

  • Store persistent data
    • Write the results of your computations to files
    • Keep a log of errors
    • Store intermediate results
  • Load previously stored files

File Types

Text

+
Human readable
Multiple powerful standards like CSV, XML, JSON and YAML
Can usually be compressed
-
Hard to parse manually
Require more memory

Binary

+
Require less memory
Are easy to write and load if the exact format is known
-
Not human readable
Editing with a hex editor is tedious
Cannot be read when the format is not known

C++ API

All required functions are provided by <fstream>.

// output file stream, alt. `ifstream`, `fstream`
std::ofstream fs{filepath [, mode]};

File streams have a considerable API, partially inherited
from multiple base classes; e.g.

operator bool;  // `true` if the stream has no errors, `false` otherwise
operator!;  // `true` if an error has occurred, `false` otherwise
operator<<;  // insert data into the stream
operator>>;  // extract values from an input stream
write(const char_type* s, std::streamsize count);  // insert binary data
read(char_type* s, std::streamsize count);  // read binary data

std::getline(std::ifstream ifs, std::string s);  // Defined in `<string>`

operator bool or operator! can be used to check if opening a file succeeded.

Text Files

Example: Writing Text

#include <fstream>  // provides `fstream`, `ifstream`, `ofstream`
#include <iostream>  // for `cerr`
int main() {
  int num = 15;
  std::ofstream fs("data.txt");  // open for writing

  if (!fs) {  // check if opening was successful
    std::cerr << "Error!" << std::endl;
    return 1;
  }

  fs << num << std::endl;
  fs << "This is a text" << std::endl;

  return 0;
}
Download write_text.cpp

Example: Appending Text

#include <fstream>  // provides fstream, ifstream, ofstream
#include <iomanip>
#include <iostream>  // for `cerr`
int main() {
  std::ofstream fs("data.txt", std::ios::app);  // open for appending

  if (!fs) {  // check if opening was successful
    std::cerr << "Error!" << std::endl;
    return 1;
  }

  fs << std::fixed << std::setprecision(2) << 36.8 << std::endl;
  fs << "Additional text" << std::endl;
  return 0;
}
Download append_text.cpp

Reading Text

#include <fstream>  // provides `fstream`, `ifstream`, `ofstream`
#include <iostream>  // for `cerr`
int main() {
  std::ifstream fs("data.txt");  // open for reading
  int num(0);

  if (fs) {  // check if opening was successful
    std::string s;

    fs >> num;  // read `int` until first whitespace character
    while (std::getline(fs, s)) {  // read line by line
      std::cout << "READ: " << s << std::endl;
    }
  }
  std::cout << "2 * num: " << 2 * num << std::endl;
  return 0;
}
Download read_text.cpp

Binary Files

Example: Writing Data

#include <fstream>
struct Data {
  int first;
  int second;
};
int main() {
  Data d = {.first=1724, .second=255};
  std::ofstream fs("data.bin", std::ios::binary);
  if (fs) {
    fs.write(reinterpret_cast<char*>(&d), sizeof(Data));
  }
  return 0;
}
Download write_binary.cpp

Example: Reading Data

#include <fstream>
#include <iostream>
struct Data {
  int first;
  int second;
};
int main() {
  Data d;
  std::ifstream fs("data.bin", std::ios::binary);
  if (fs) {
    fs.read(reinterpret_cast<char*>(&d), sizeof(d));
  }
  std::cerr << "first: " << d.first << " second: " << d.second << std::endl;
  return 0;
}
Download read_binary.cpp

Example: Write Array

#include <fstream>
#include <limits>
#include <vector>
using std::numeric_limits, std::ofstream, std::vector;
int main() {
  vector<unsigned> v = {0, numeric_limits<unsigned>::max(), 255, 0xff000000, 1724};
  std::ofstream fs("array.bin", std::ios::binary);
  if (fs) {
    fs.write(reinterpret_cast<const char *>(v.data()), v.size() * sizeof(unsigned));
  }
  return 0;
}
Download write_array.cpp

Start by investigating the file size (eg. ls -l)

Decode the values of the array: xxd [-b] file.bin (hint: endianness)

Dec Hex  Bin      Dec Hex  Bin
  0   0 0000        8   8 1000
  1   1 0001        9   9 1001
  2   2 0010       10   A 1010
  3   3 0011       11   B 1011
  4   4 0100       12   C 1100
  5   5 0101       13   D 1101
  6   6 0110       14   E 1110
  7   7 0111       15   F 1111
      

Investigate with a proper hex editor (eg. Okteta w/ Tools->Decoding Table)

Exercise

  1. Write your name in a text file. Then write a C++ program to read that file and print its content to stdout.
  2. Write a C++ program that loads the array written by write_array.cpp. The program must print all numbers in the array to stdout, separated by commas.

Questions
and feedback...