Read from file
Contents
Read from file#
Here we will look at a simple example of how to read a set of numbers from a text file. Our two most common use cases for reading from file are
that our computation/simulation needs some input data; or
that we need to pass in many control parameters (step sizes, tolerances, etc.) for our program.
For the example below we will assume that the numbers are organised in a table that we should read row by row. A simple table format is most suitable for the first case above. For the second case, if you are writing a code that needs a large number of configuration parameters, you probably want to use some standard structured file format, e.g. YAML, which you can use with C++ via external libraries such as yaml-cpp.
Minimal example#
Assume we have a data table file x_y_fxy.dat
that look like this:
# x y f(x,y)
0.0000e+00 0.0000e+00 0.0000e+00
0.0000e+00 1.9635e-01 3.8553e-02
0.0000e+00 3.9270e-01 1.5421e-01
0.0000e+00 5.8905e-01 3.4698e-01
0.0000e+00 7.8540e-01 6.1685e-01
1.9635e-01 0.0000e+00 1.9635e-01
1.9635e-01 1.9635e-01 2.4247e-01
1.9635e-01 3.9270e-01 3.6569e-01
1.9635e-01 5.8905e-01 5.6599e-01
1.9635e-01 7.8540e-01 8.4336e-01
3.9270e-01 0.0000e+00 3.9270e-01
3.9270e-01 1.9635e-01 4.6150e-01
3.9270e-01 3.9270e-01 6.0723e-01
3.9270e-01 5.8905e-01 8.2971e-01
3.9270e-01 7.8540e-01 1.1288e+00
5.8905e-01 0.0000e+00 5.8905e-01
5.8905e-01 1.9635e-01 6.9558e-01
5.8905e-01 3.9270e-01 8.7831e-01
5.8905e-01 5.8905e-01 1.1363e+00
5.8905e-01 7.8540e-01 1.4688e+00
7.8540e-01 0.0000e+00 7.8540e-01
7.8540e-01 1.9635e-01 9.4459e-01
7.8540e-01 3.9270e-01 1.1780e+00
7.8540e-01 5.8905e-01 1.4829e+00
7.8540e-01 7.8540e-01 1.8566e+00
The following code will read this file and save the rows in a vector of vectors using only the standard C++ library. The example also shows how the comment line starting with #
can be ignored when reading the data.
Note
You can also use Armadillo to very easily read a data table — see the introduction to Armadillo page.
#include <iostream>
#include <sstream>
#include <string>
#include <fstream>
#include <vector>
int main()
{
// Set the filename
std::string filename = "x_y_fxy.dat";
// A vector of vectors to store the the rows in the input file
std::vector< std::vector<double> > input_data;
// Create a filestream instance "myfile" and use it to read the file
std::fstream myfile;
myfile.open(filename);
if (myfile.is_open()) // This checks that the file was opened OK
{
// Some temporary variables we'll use
std::string line;
double x, y, f;
// Read file line by line
while (std::getline(myfile, line))
{
// Skip lines with "#" at the first position
if (line.at(0) == '#')
{
continue;
}
else
{
// Parse the string (line) and interpret it as three
// double variables (x, y, f)
std::stringstream mysstream(line);
mysstream >> x >> y >> f;
// Save the three values in a new vector in input_data
std::vector<double> triplet = {x, y, f};
input_data.push_back(triplet);
}
}
}
else
{
std::cout << "Unable to open the file " << filename;
}
// Close the input file
myfile.close();
//
// (Now do something useful with the data...)
//
// All is well. Exit program with return code 0.
return 0;
}
In a larger program, it’s usually better to write a separate function for reading data from file rather than placing this code directly in the main program.