# File Input/Output

## File Streams

Standard streams are automatically opened. Other files must be opened explicitly. Files can be input streams (ifstream), output streams (ofstream), or either/both (fstream).

#include <fstream>


or

#include <ofstream>
#include <ifstream>


as needed.

## Open

First a stream object must be declared.

  ifstream input;


Then the stream can be attached to a named file

  input.open(inFileName);


This assumes the file exists and is opened for reading only.

For output use

  ofstream output;
output.open(outFileName);


This file will be emptied if it exists or created if it does not exist, and will be opened in write-only mode.

   fstream myfile;
myfile.open(myfileName);


## Modifiers

We can control the characteristics of the file with modifiers

• ios::in open for input (read). Default for ifstream.
• ios::out open for output (write). Default for ofstream.
• ios::binary open as binary (not text)
• ios::app append
• ios::trunc if file exists, overwrite (default for ofstream)

Use a pipe (|) to combine them

   ofstream myfile;
myfile.open("myfile.dat",ios::binary | ios::app);


## Inquiring

All inquiry methods return a bool (Boolean). To check whether a file is open

   myfile.is_open()


To check whether a file opened for reading is at the end

   myfile.eof()


To test for any error condition

   myfile.good()


## Close

Much of the time, it is not necessary to close a file explicitly. Files are automatically closed when execution terminates. If many files are opened, it is good practice to close them before the end of the run.

   myfile.close();


## Rewind

An open unit can be rewound. This places the file pointer back to the beginning of the file. The default is to rewind a file automatically when it is closed.

These are C-style functions and are in <cstdio>.

   rewind(mystream)


You can also seek to position 0

   fseek(mystream,0,SEEK_SET)


where rewind clears the end-of-file and error indicators, whereas fseek does not.

# Writing to a File

We write to a file much like to a standard stream. In this example, we assume that var1, var2, and var3 are arrays or vectors of length nlines.

  ofstream out("outfile.txt");
out<<"column1,column2,column3\n";
for (int i=0;i<nlines;++i) {
out<<var1[i]<<","<<var2[i]<<","<<var3[i]<<"\n';
}


The extraction operator works on file objects as well as on cin:

#include <fstream>
#include <iostream>

int main() {

float var1, var2;
std::ifstream myfile("data.txt");
if (myfile.is_open()) {
while ( ! myfile.eof() ) {
myfile >> var1 >> var2;
std::cout<<var1<<" "<<var2<<"\n";
}
}
}



Although this method works, it has a number of drawbacks. As we learned for console IO, the extraction operator assumes the separator is whitespace. It can be thrown off when attempting to convert a string into a numerical type. It also is inflexible. We will discuss more advanced methods in the next chapter.

Exercise

Write a program that creates a file mydata.txt containing four rows consisting of

1 2 3
4 5 6
7 8 9
10 11 12


Either rewind or reopen the file and read the data back. Write a loop to add 1 to each value and print each row to the console. Note that if you choose to rewind, the file will have to be opened read/write. If you close it and reopen it, it will have to be reopened in write mode. You may use a statically-sized array for the data. In the next chapter we will learn a more flexible method of reading lines of files.

Example Solution

#include <iostream>
#include <fstream>

using namespace std;

int main() {
fstream myfile;
myfile.open("mydata.txt", ios::out);

for (int i=1; i<=12; ++i) {
myfile << i;
if (i%3==0) {
myfile << "\n";
} else {
myfile << " ";
}
}
myfile.close();

myfile.open("mydata.txt", ios::in);

int x[4][3];
if (myfile.is_open()) {
for (int i=0; i<4; ++i) {
myfile>>x[i][0]>>x[i][1]>>x[i][2];
}
} else {
cout<<"Unable to open file";
return 1;
}

for (int i=0; i<4; ++i) {
for (int j=0; j<3; ++j) {
x[i][j]++;
}
}
for (int i=0; i<4; ++i) {
for (int j=0; j<3; ++j) {
cout << x[i][j] << " ";
}
cout << "\n";
}
}



Previous