By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
443,750 Members | 1,456 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 443,750 IT Pros & Developers. It's quick & easy.

file I/O question

P: n/a
I'm trying to overload the << and >> operators to serialize a class to
disk. It writes things correctly, but it doesn't read them back correctly.

Can someone tell what I'm doing wrong? Here is an example demonstrating
my problem.

------- tmp.cc --------------
#include <cstdlib>
#include <ctime>
#include <fstream>
#include <iostream>

class foo {
private:
long keymap[5];
int joymap[5];
int joystick;
bool useJoystick, useDpad;

friend std::ostream &operator<<(std::ostream &, const foo &);
friend std::istream &operator>>(std::istream &, foo &);

public:
foo(bool init = true);
};

foo::foo(bool init) {
if (init) {
for (int i = 0; i < 5; i++) {
keymap[i] = static_cast<long>(rand() % 1000);
joymap[i] = rand() % 16;
}

joystick = -1;
useJoystick = useDpad = false;
}
}

std::ostream &operator<<(std::ostream &output, const foo &f) {
for (int i = 0; i < 5; i++) {
output << f.keymap[i];
output << f.joymap[i];
}

output << f.joystick << f.useJoystick << f.useDpad;

return output;
}

std::istream &operator>>(std::istream &input, foo &f) {
for (int i = 0; i < 5; i++) {
input >> f.keymap[i];
input >> f.joymap[i];
}

input >> f.joystick >> f.useJoystick >> f.useDpad;

return input;
}

int main(int, char **) {
srand(time(NULL));

foo f, f2(false);

std::fstream out("foo.bar",
std::ios_base::out | std::ios_base::binary);

if (!out) {
std::cerr << "fatal: unable to open foo.bar for writing\n";
return -1;
}

out << f;
out.close();

std::cout << "wrote the following to foo.bar...\n" << f << "\n\n";

std::fstream in("foo.bar",
std::ios_base::in | std::ios_base::binary);

if (!in) {
std::cerr << "fatal: unable to open foo.bar for reading\n";
return -1;
}

in >> f2;
in.close();

std::cout << "read the following from foo.bar...\n" << f2 << '\n';

return 0;
}
-----------------------------

This is the output I get with mingw/g++ 3.4.2

$ g++ -W -Wall -O2 tmp.cc
$ ./a.exe
wrote the following to foo.bar...
252694219161177692989-100

read the following from foo.bar...
-12009252579208987889302009252574400902539976962368 368020092919242009145480255255

$ cat foo.bar
252694219161177692989-100

The data is being written correctly, I'm just not sure why I can't do
the reverse when I read it from the file.

Thanks,

--John Ratliff
Sep 1 '05 #1
Share this Question
Share on Google+
3 Replies


P: n/a
John Ratliff wrote:
I'm trying to overload the << and >> operators to serialize a class to
disk. It writes things correctly, but it doesn't read them back correctly.

Can someone tell what I'm doing wrong? Here is an example demonstrating
my problem.

------- tmp.cc --------------
[redacted
std::ostream &operator<<(std::ostream &output, const foo &f) {
for (int i = 0; i < 5; i++) {
output << f.keymap[i];
output << f.joymap[i];
}

output << f.joystick << f.useJoystick << f.useDpad;

return output;
}

std::istream &operator>>(std::istream &input, foo &f) {
for (int i = 0; i < 5; i++) {
input >> f.keymap[i];
input >> f.joymap[i];
}

input >> f.joystick >> f.useJoystick >> f.useDpad;

return input;
}

[redacted]


You might want to put some spaces in there. Remember, just 'cause you
opened it up in binary mode, doesn't mean the data you put out using
"<<" is. It has to do with newline translations. So when you output
the members of f, it puts them out in ASCII.

That is,

if all member variables of f are 0 (hypothetical), you'll get the
following output:

0000000000000

How is the input parser supposed to know where each field begins?

Try:

std::ostream& operator<<(std::ostream& os, const foo& f)
{
for (int i = 0; i < 5 ; ++i)
os << f.keymap[i] << " " << f.joymap[i] << " ";
os << f.joystick << " "
<< f.useJoystick << " "
<< f.useDpad << std::endl;
return os;
}

Now, you have the following outputs (again, assuming all 0)

0 0 0 0 0 0 0 0 0 0 0 0 0

So the input parser can determine where each field begins. Note that I
put an 'endl' after the last value.

Sep 1 '05 #2

P: n/a
red floyd wrote:
John Ratliff wrote:
I'm trying to overload the << and >> operators to serialize a class to
disk. It writes things correctly, but it doesn't read them back
correctly.

Can someone tell what I'm doing wrong? Here is an example
demonstrating my problem.

------- tmp.cc --------------
[redacted
std::ostream &operator<<(std::ostream &output, const foo &f) {
for (int i = 0; i < 5; i++) {
output << f.keymap[i];
output << f.joymap[i];
}

output << f.joystick << f.useJoystick << f.useDpad;

return output;
}

std::istream &operator>>(std::istream &input, foo &f) {
for (int i = 0; i < 5; i++) {
input >> f.keymap[i];
input >> f.joymap[i];
}

input >> f.joystick >> f.useJoystick >> f.useDpad;

return input;
}

[redacted]

You might want to put some spaces in there. Remember, just 'cause you
opened it up in binary mode, doesn't mean the data you put out using
"<<" is. It has to do with newline translations. So when you output
the members of f, it puts them out in ASCII.

That is,

if all member variables of f are 0 (hypothetical), you'll get the
following output:

0000000000000

How is the input parser supposed to know where each field begins?

Try:

std::ostream& operator<<(std::ostream& os, const foo& f)
{
for (int i = 0; i < 5 ; ++i)
os << f.keymap[i] << " " << f.joymap[i] << " ";
os << f.joystick << " "
<< f.useJoystick << " "
<< f.useDpad << std::endl;
return os;
}

Now, you have the following outputs (again, assuming all 0)

0 0 0 0 0 0 0 0 0 0 0 0 0

So the input parser can determine where each field begins. Note that I
put an 'endl' after the last value.


I was thinking along those lines, but I wasn't sure.

Yeah, I know binary mode only means newline translation, but for some
reason I thought it would add terminators or spaces for me. Don't know
why I had that thought.

Thanks,

--John Ratliff
Sep 1 '05 #3

P: n/a
John Ratliff wrote:
I'm trying to overload the << and >> operators to serialize a class to
disk. It writes things correctly, but it doesn't read them back correctly.

Can someone tell what I'm doing wrong? Here is an example demonstrating
my problem.
[snip]
The data is being written correctly, I'm just not sure why I can't do
the reverse when I read it from the file.

If you look, I bet you'll find that the data in the file is in text
format, not binary. That's because the default stream insertion (<<)
and extraction (>>) operators are for formatted (i.e., text-mode) I/O
only, and I believe they force the file mode to text, no matter what
you opened it as. Use ostream::write() and istream::read() in your
operator functions instead of the standard insertion/extraction
operators to read and write in non-text format. You should probably
also check in your operator functions to see if the file is in binary
mode or not.

Alternately, use text mode and separate the values with spaces. This
might yield smaller files if your numbers are generally small: a binary
integer of value 2 would take up four bytes whereas the text version
would take up 2 (one for the text digit, one for the space). Using hex
might also help if the numbers are unsigned.

Cheers! --M

Sep 1 '05 #4

This discussion thread is closed

Replies have been disabled for this discussion.