Topic : Simple File I/O Using C++
Author : John Peregrine
Page : 1 Next >>
Go to page :


Simple File I/O Using C++
by John Peregrine


Preface
I have been reviewing the message boards and posted articles on file input and output, and I just think itís that time again. File I/O is easier than baking cookies when used in conjunction with C++. In this article, I will be explaining to all of you how exactly to handle just about every aspect of file input and output using both ASCII and binary methods, and the best part is that itís all done using C++.

Getting started, ASCII output
To get anything to work using the methods here, you must first include <fstream.h>. This is actually an extension onto <iostream.h>, for those of you buffs out there that already like to use streams for console input and output. Actually, <iostream.h> is already included with <fstream.h>, so you really donít need to include both into your source files anymore, but if you prefer to just explicitly include both, feel free to do so. Letís begin by showing you the class designed for file handling, and Iíll show you how to do ASCII I/O. If you guessed "fstream," youíre exactly right! But for the methods of this article, weíll be using the two classes "ifstream" and "ofstream" for input and output, respectively.

If you have ever worked with the two console streams "cin" and "cout," then this will become a breeze for you. Weíll work with just the output part for now, and start by declaring an object for it.


ofstream fout;


Thatís all for that, but to open the file, you must call ofstream::open() like this.


fout.open("output.txt");


You could have also just as well opened the file as you declared the stream by passing the filename as a parameter to the constructor of the object.


ofstream fout("output.txt");


This will be our selected method of declaring objects, since itís still rather simple to see how to create and open the file. By the way, if the file you are opening for output does not exist, it will be created for you, so there is no need to ever worry about creating the file. Now to output to the file, it works exactly like how you would output to "cout." For those of you that donít know "cout" for console output, then hereís an example.


int num = 150;
char name[] = "John Doe";
fout << "Here is a number: " << num << "\n";
fout << "Now here is a string: " << name << "\n";



Now to save the file, you must close the file, or flush the buffer to the file. Closing the file will not let you access it anymore, so only call it when you are done using the file and it will automatically save the file for you. Flushing the buffer will write the buffer to the file and still keep the file open, so use this function when necessary. Flushing is done by another output looking call, and closing is done by a method call. Like this:


fout << flush;
fout.close();



Now the contents of the file when you open it in a text editor will read:


Here is a number: 150
Now here is a string: John Doe


Itís that simple! Now letís move on to file input, which can be a bit trickier, so make sure you have the simple streams down first. Become familiar with the "<<" and ">>" operators, because youíll need them again. So here we goÖ

Moving on, ASCII input
Input is, again, exactly the same as using the "cin" stream. It resembles the file output stream weíve already discussed, but there are a few things you have to worry about. Before we go over the tricky stuff, letís just begin with a simple text file that contains:


12
GameDev
15.45
L
This is really awesome!


To open this file, you must create the in-stream object, like so.


ifstream fin("input.txt");


Now letís read in the first four lines. Remember how you used the "<<" operator to insert variables and symbols into the stream? Well, to go along with the "<<" (insertion) operator, thereís the ">>" (extraction) operator. And it works just the same. Look at this snippet below.


int number;
float real;
char letter, word[8];

fin >> number;
fin >> word;
fin >> real;
fin >> letter;



It's also possible to put these four lines reading the file into one, simpler line.


fin >> number >> word >> real >> letter;

How does this work? After each white space in the file, the ">>" operator will stop reading in the contents, until another >> operator is encountered. Since each of the four lines we were reading in was separated by a new line (which is a white space character), the ">>" operator puts only that line into the separate variables. Thatís how both of the code's samples would work.

Letís not forget about that last line in our file, though.


This is really awesome!


If we want this whole line in one char array, we cannot do it with the ">>" operator because the spaces (white space) between each word would stop the file extraction. For instance, if we had said:


char sentence[101];
fin >> sentence;



We'd want sentence to now contain, "This is really awesome!" But because of the white space, it now only contains "This". Obviously, there is a way to read in the whole line, and it is the method getline(). This is how we would do it.


fin.getline(sentence, 100);


Here are the parameters to the function. The first parameter is obviously the char array we want to read in to. The second is the maximum number of characters we will read in until we encounter a new line. So now sentence contains "This is really awesome!" just like we wanted.

You should now know how to do input and output with ASCII files. But we canít stop there, because binary files now await us.

Continuing on, binary input and output
Binary files are a little bit more complicated, but they are still rather simple. The first thing you should note is that we do not use the insertion and extraction operators anymore. You can, but it will not write as binary. You must use the methods read() and write() for binary. To create a binary file, look at the next line.


ofstream fout("file.dat", ios::binary);


This will open the file as binary, instead of the default ASCII mode. Letís start first by writing to the file. The write() method takes two parameters. The first is a char pointer to the object you wish to write, and the second is the number of bytes the object is. To illustrate this, letís show an example.


int number = 30;
fout.write((char *)(&number), sizeof(number));



The first parameter is written as "(char *)(&number)". This just type casts the integer variable to a char pointer. If you donít understand how that works, then you can leaf through a C++ book on pointers if necessary. The second parameter was written as "sizeof(number)". The sizeof() function just returns an integer of the number of bytes a variable is. And thatís it!

The best part of using binary files is that you can write an entire structure to the file in one line. Letís say you had a structure with 12 different items in it. Using an ASCII file would make you write each individual member of the structure one at a time, but binary files can do it all for you. Letís look at this.


struct OBJECT
{
   int number;
   char letter;
} obj;

obj.number = 15;
obj.letter = ĎMí;

fout.write((char *)(&obj), sizeof(obj));



That would write the entire structure for you! Letís move on to input now. Input will be a cinch now because the read() function takes exactly the same parameters as write(), and it works exactly the same.


ifstream fin("file.dat", ios::binary);

fin.read((char *)(&obj), sizeof(obj));



I donít even have to explain how that works, because it works just the same as write(). Binary files can be even easier that ASCII files, but the downside is that you cannot edit binary files with a simple text editor. But with that said, let me finish up by explaining some more methods to the ifstream and ofstream objects.

Finishing up, More methods
Iíve already explained ASCII and binary files, so hereís the low-down on all the functions that I didnít cover yet.

Checking files
Youíve already learned the open() and close() methods, but hereís some you might want to use.

The method good() will return a boolean to whether or not the file opening was good.

Similarly, bad() will return a boolean to whether or not the file opening was bad. If it was bad, do not continue with the file operations.

The last checking method is fail(), which is somewhat like the method bad(), but not as severe.

Reading files
The method get() will return one character at a time.

The method ignore(int,char) will ignore a certain number of characters, but you must pass it two parameters. The first is the number of characters to ignore. The second is a character that, when encountered, will stop ignoring characters. For instance,


fin.ignore(100, Ď\ní);


Will ignore 100 characters, or ignore all characters up to, and including the Ď\ní character.

The method peek() will return

Page : 1 Next >>