cerr << "Can't open " << file << " file for output.\n";
exit(EXIT_FAILURE);
}
cout << "Enter guest names (enter a blank line to quit):\n";
string name;
while (getline(cin,name) && name.size() > 0)
{
fout << name << endl;
}
fout.close();
// show revised file
fin.clear(); // not necessary for some compilers
fin.open(file);
if (fin.is_open())
{
cout << "Here are the new contents of the "
<< file << " file:\n";
while (fin.get(ch))
cout << ch;
fin.close();
}
cout << "Done.\n";
return 0;
}
Here’s a sample first run of the program in Listing 17.18:
Enter guest names (enter a blank line to quit):
Genghis Kant
Hank Attila
Charles Bigg
Here are the new contents of the guests.txt file:
Genghis Kant
Hank Attila
Charles Bigg
Done.
At this point the guests.txt file hasn’t been created, so the program doesn’t preview the file.
Next time the program is run, however, the guests.txt file does exist, so the program does preview the file. Also note that the new data are appended to the old file contents rather than replacing them:
Here are the current contents of the guests.txt file:
Genghis Kant
Hank Attila
Charles Bigg
Enter guest names (enter a blank line to quit):
Greta Greppo
LaDonna Mobile
Fannie Mae
Here are the new contents of the guests.txt file:
Ghengis Kant
Hank Attila
Charles Bigg
Greta Greppo
LaDonna Mobile
Fannie Mae
Done.
You should be able to read the contents of guest.txt with any text editor, including the editor you use to write your source code.
Binary Files
When you store data in a file, you can store the data in text form or in binary format. Text form means you store everything as text, even numbers. For example, storing the value -2.324216e+07 in text form means storing the 13 characters used to write this number. That requires converting the computer’s internal representation of a floating-point number to character form, and that’s exactly what the << insertion operator does. Binary format, on the other hand, means storing the computer’s internal representation of a value. That is, instead of storing characters, the computer stores the (typically) 64-bit double representation of the value. For a character, the binary representation is the same as the text representation—the binary representation of the character’s ASCII code (or equivalent). For numbers, however, the binary representation is much different from the text representation (see Figure 17.7).
Figure 17.7. Binary and text representations of a floating-point number.
Each format has advantages. The text format is easy to read. With it, you can use an ordinary editor or word processor to read and edit a text file. You can easily transfer a text file from one computer system to another. The binary format is more accurate for numbers because it stores the exact internal representation of a value. There are no conversion errors or round-off errors. Saving data in binary format can be faster because there is no conversion and because you may be able to save data in larger chunks. And the binary format usually takes less space, depending on the nature of the data. Transferring to another system can be a problem, however, if the new system uses a different internal representation for values. Even different compilers on the same system may use different internal representations for structure layouts. In these cases, you (or someone) may have to write a program to translate one data format to another.
Let’s look at a more concrete example. Consider the following structure definition and declaration:
const int LIM = 20;
struct planet
{
char name[LIM]; // name of planet
double population; // its population
double g; // its acceleration of gravity
};
planet pl;
To save the contents of the structure pl in text form, you can use this:
ofstream fout("planets.dat", ios_base:: out | ios_base::app);
fout << pl.name << " " << pl.population << " " << pl.g << "\n";
Note that you have to provide each structure member explicitly by using the membership operator, and you have to separate adjacent data for legibility. If the structure contains, say, 30 members, this could get tedious.
To save the same information in binary format, you can use this:
ofstream fout("planets.dat",
ios_base:: out | ios_base::app | ios_base::binary);
fout.write( (char *) &pl, sizeof pl);
This code saves the entire structure as a single unit, using the computer’s internal representation of data. You won’t be able to read the file as text, but the information will be stored more compactly and precisely than as text. And it is certainly easier to type the code. This approach makes two changes:
• It uses a binary file mode.
• It uses the write() member function.
Let’s examine these changes more closely.