1.9.  File Streams

[ fromfile: filestreams.xml id: filestreams ]

Streams are used for reading from or writing to files, network connections, and also strings. One useful feature of streams is that they make it easy to produce strings from mixed types of data. In Example 1.8 we will create some strings from characters and numerics and write them to a file.

Example 1.8. src/stl/streams/streams.cpp

[ . . . . ]

#include <iostream>
#include <sstream>
#include <fstream>

int main() {
    using namespace std;
    ostringstream strbuf;

    int lucky = 7;
    float pi=3.14;
    double e=2.71;
    
    cout << "An in-memory stream" << endl;
    strbuf << "luckynumber: " << lucky << endl
           << "pi: " << pi << endl
           << "e: " << e << endl;

    string strval = strbuf.str(); 1
    cout << strval;

    ofstream outf;  2
    outf.open("mydata");  3
    outf << strval ;   
    outf.close();

1

Convert the stringstream to a string.

2

An output file stream.

3

Creates (or overwrites) a disk file for output.

After the strings have been written, we have a couple of choices of how to read them. We can use simple input operators to read from the file and, since there is whitespace between records, the insertion operator might look like Example 1.9

Example 1.9. src/stl/streams/streams.cpp

[ . . . . ]

    cout << "Read data from the file - watch for errors." << endl;
    string newstr;  
    ifstream inf;  1
    inf.open("mydata");   
    if(inf) {  /*Make sure the file exists before attempting to read.*/
      int lucky2;
      inf >> newstr >> lucky2;
      if (lucky != lucky2)
        cerr << "ERROR! wrong " << newstr << lucky2  << endl;
      else
	cout << newstr << " OK" << endl;

      float pi2;
      inf >> newstr >> pi2;
      if (pi2 != pi) 
	cerr << "ERROR! Wrong " << newstr << pi2 << endl;
      else
	cout << newstr << " OK" << endl;
    
      double e2;
      inf >> newstr >> e2;
      if (e2 != e) 
	cerr << "ERROR: Wrong " << newstr << e2 <<  endl;
      else
	cout << newstr << " OK" << endl;
      inf.close();   
    }

1

An input file stream

We can read files line-by-line and deal with each line as a single string, as shown in Example 1.10

Example 1.10. src/stl/streams/streams.cpp

[ . . . . ]

    cout << "Read from file line-by-line" << endl;
    inf.open("mydata");
    if(inf) {
      while (not inf.eof()) {
        getline(inf, newstr);
        cout << newstr << endl;
      }
      inf.close();
    }
    return 0;
}

Example 1.11 does the same things using Qt4 files, strings, and streams. In this example we also make use of two other Qt types: QString, which provides a powerful and flexible string representation, and QFile, which provides an interface for handling files.

Example 1.11. src/qtstreams/files/qdemo.cpp

#include <QTextStream>
#include <QString>
#include <QFile>

QTextStream cout(stdout, QIODevice::WriteOnly);
QTextStream cerr(stderr, QIODevice::WriteOnly);

int main() {
  QString str, newstr;
  QTextStream strbuf(&str);  /*strbuf is initialized with the address of str.*/

  int lucky = 7;
  float pi = 3.14;
  double e = 2.71;
    
  cout << "An in-memory stream" << endl;
  strbuf << "luckynumber: " << lucky << endl
	 << "pi: " << pi << endl
	 << "e: " << e << endl;

  cout << str;
  
  QFile data("mydata");
  data.open(QIODevice::WriteOnly);  1
  QTextStream out(&data);  2
  out << str ;   
  data.close();

  cout << "Read data from the file - watch for errors." << endl;
  if(data.open(QIODevice::ReadOnly)) { /*Make sure the file exists before 
                                         attempting to read.*/
    QTextStream in(&data);   3
    int lucky2;
    in >> newstr >> lucky2;
    if (lucky != lucky2)
      cerr << "ERROR! wrong " << newstr << lucky2  << endl;
    else
      cout << newstr << " OK" << endl;

    float pi2;
    in >> newstr >> pi2;
    if (pi2 != pi) 
      cerr << "ERROR! Wrong " << newstr << pi2 << endl;
    else
      cout << newstr << " OK" << endl;
    
    double e2;
    in >> newstr >> e2;
    if (e2 != e) 
      cerr << "ERROR: Wrong " << newstr << e2 <<  endl;
    else
      cout << newstr << " OK" << endl;
    data.close();   
  }

  cout << "Read from file line-by-line" << endl;
  if(data.open(QIODevice::ReadOnly)) {
    QTextStream in(&data);   4
    while (not in.atEnd()) {
      newstr = in.readLine();
      cout << newstr << endl;
    }
    data.close();
  }
  return 0;
}

1

Creates (or overwrites) a disk file for output.

2

An output file stream.

3

An input file stream

4

An input file stream

The address-of operator, used to initialize strbuf will be discussed in Section 1.14.1.