Public Group

# Need help with binary IO

This topic is 4417 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

Okay, I've always kind of neglected IO... I can do some text IO, but I want to learn to do binary so my saved game files can't be tampered with as easily. Also, I've heard it's easier. Well... Here's some code from my book:
struct status
{
char name[80];
float balance;
unsigned long account_number;
};

void main(void)
{
struct status acc;
strcopy(acc.name, "Lars Klander");
acc.balance = 1234.56;
acc.account_number = 98765432;
ofstream outbal("balance.asc", ios::out | ios::binary);
if(!outbal)
{
cout << "Cannot open output file." << endl;
exit (1);
}
outbal.write((unsigned char *) &acc, sizeof(struct status));
outbal.close();
}


Well, it would be awesome if it was that easy, but it didn't work when I tried it. And I can't see how it could considering acc is a structure... So I tried writing each variable one at a time. The name writes easy enough. But for the integer I split it into four unsigned chars by bit shifting each section of 8 bits left to the very end (to get rid of the 1s on the left), then all the way to the right. And for the float, when I tried to bit shift it, I got errors... It seems as if my compilers telling me I can't bit shift floats. Well. Am I like going about this the wrong way? As I said, IO is not my strong suit and I don't know much about this. So is there an easier/better/more correct way to write to a binary file?

##### Share on other sites
I think that book is trying to teach you C AND C++ mixed together at once... More like C+.

struct t {    int a;};t m; // can't do this, it won't know about t// so you dostruct t m; // now it knows that t is a struct// this can be taken away by:typedef struct {    int a;} t;t m; // it's fine, t is now a typedef for it

You should take out the "struct" from struct t acc; and sizeof(struct t);. C++ doesn't have that problem.

EDIT: Don't change everything into a char, just cast it's address:
struct t {    int a;    other_POD b;};os.write(reinterpret_cast<char*>(&my_t), sizeof(my_t));

Since each char is a byte, and sizeof returns the size in bytes, it's easier to know the address in bytes rather than something else.

##### Share on other sites
Ah, that's awesome! Now that is easy. Thanks alot.

##### Share on other sites
Quote:
 Original post by K A Z EOkay, I've always kind of neglected IO... I can do some text IO, but I want to learn to do binary so my saved game files can't be tampered with as easily. Also, I've heard it's easier. Well... Here's some code from my book:*** Source Snippet Removed ***

Throw your book away. Now. Burn it. I feel sick looking at that code.

But I will clutch a hot water bottle to my tummy long enough to fix it:

struct status {  std::string name;  float balance;  unsigned long account_number;  status(const std::string& name, float balance, unsigned long account_number):  name(name), balance(balance), account_number(account_number) {}};template<typename T>void write_primitive(ostream& os, const T& value) {  os.write(reinterpret_cast<unsigned char*>(&value), sizeof(T));}void write_string_binary(ostream& os, const std::string& s) {  write_primitive(os, s.length());  os.write(s.c_str(), s.length());}int main() {    status acc("Lars Klander", 1234.56, 98765432);    ofstream outbal("balance.asc", ios::out | ios::binary);    if(outbal) {        cout << "Cannot open output file." << endl;        exit(1);    }    write_string_binary(outbal, acc.name);    write_primitive(outbal, acc.balance);    write_primitive(outbal, acc.account_number);}

Please note how I handle the string: I output a *length count first*. You *can* output a POD containing a char[] in the indicated way, but it doesn't treat the char[] as "a string", but as the array - and writes out all 80 characters, most of which are garbage.

The code as given should have "worked" for writing, but just perhaps not produced the file contents you expected.

You should, as I commonly say, "Stop. Read this." (And also this.) And also note that the "mode" with which a file is opened is a completely different thing from the "mode" in which you write the data. Nothing stops you from using operator<< on a "binary file" (fstream opened with ios::binary), or .write() on a "text file" - it's just that you usually don't want to.

1. 1
Rutin
19
2. 2
3. 3
JoeJ
15
4. 4
5. 5

• 21
• 19
• 11
• 13
• 17
• ### Forum Statistics

• Total Topics
631697
• Total Posts
3001763
×