Join Bytes! wrote:[color=blue]
> Hi,
>
> I have always used fopen and FILE* to load and save structures to file.
> I am trying to convert all the older code to use proper C++ calls...
> the following code works properly but I would like to know if I am
> using the fstream methods properly. (as long as I am cleaning up I
> might as well do it right). By the way, this is just a bogus example
> with a structure, values and filename for demonstration purposes.[/color]
See the FAQ for more robust techniques that will work with all classes
and structs not just ones without virtual functions or, e.g.,
std::vectors:
http://www.parashift.com/c++-faq-li...ialization.html
And check out Boost's serialization library:
http://boost.org/libs/serialization/doc/index.html
[color=blue]
> PS-> I have a funny feeling casting my structure to a char* is the
> wrong approach! :)[/color]
For binary mode, you'll have to do that cast eventually.
[color=blue]
> #include <iostream>
> #include <fstream>
>
> struct stAnything
> {
> int nInteger;
> long lLong;
> char cChar;
> double dDouble;
> };
>
> int main(void)[/color]
Using void like that is an "abomination"
(
http://www.research.att.com/~bs/sibling_rivalry.pdf).
[color=blue]
> {
> std::string sFilename = "C:/test.bin";[/color]
Should be const.
[color=blue]
> stAnything stSomeStructure;
>
> stSomeStructure.nInteger = 5; // bogus values
> stSomeStructure.lLong = 10;
> stSomeStructure.cChar = 'A';
> stSomeStructure.dDouble = 5.1;
>
> // Save the structure to a binary file
> std::ofstream outFile;
> outFile.open(sFilename.c_str(), std::ofstream::out |
> std::ofstream::binary);[/color]
Prefer to open and close with the constructor and destructor,
respectively, unless you need to do differently. (In this test program,
you would actually need to close the output file manually or else move
the serialization to a separate function so the file is closed via the
destructor when the function returns.)
[color=blue]
> if (!outFile.is_open())[/color]
Better would be:
if( !outFile )
[color=blue]
> {
> std::cout << "Could not open the file for output." << std::endl;
> return 1;
> }
> outFile.write((const char *) &stSomeStructure, sizeof(stAnything));[/color]
You didn't check that the write succeeded, and you should use C++-style
casts - reinterpret_cast would be appropriate here to signal a
potentially shady conversion.
Similar comments apply to the read portion.
[color=blue]
> outFile.close();
>
> // Clear the structure
> stSomeStructure.nInteger = 0;
> stSomeStructure.lLong = 0;
> stSomeStructure.cChar = ' ';
> stSomeStructure.dDouble = 0.0;
>
> // Load the structure from a binary file
> std::ifstream inFile;
> inFile.open(sFilename.c_str(), std::ofstream::in |
> std::ofstream::binary);
> if (!inFile.is_open())
> {
> std::cout << "Could not open the file for input." << std::endl;
> return 1;
> }
> inFile.read((char *) &stSomeStructure, sizeof(stAnything));
> inFile.close();
>
> // Show the loaded contents
> std::cout << "{" << stSomeStructure.nInteger << ", " <<
> stSomeStructure.lLong << ", " <<
> stSomeStructure.cChar << ", " <<
> stSomeStructure.dDouble << "} " << std::endl;
> return 0;
> }[/color]
You might also be interested in this section of the FAQ:
http://www.parashift.com/c++-faq-lite/input-output.html
Cheers! --M