Coders only: Problem with writing strings with ios::binary

14 replies [Last post]
Joined: 04/29/2011

I'm writing a program in c++.
I need to write some strings from header to a binary file.
I wrote it like this:

fstream f;
f.open("file",ios::out|ios::binary);
f.write((char *)&lib,sizeof(lib));

When i read it in another function with f.read it crashes.
What should I do?

Joined: 08/06/2010

You can't read with that stream because it was only opened in ios::out mode. You need to add ios::in, or close it and reopen it. Wink

Another Planet finally has an official release! Download chapters 1 through 3 here! Thank you for waiting so long while I kept starting over.

Joined: 04/29/2011

I open it in ios::in in another function, so that's not that big of a deal.

Here's an example of the lib struct:

typedef struct
{
    string isbn;
    string titolo;
    string autore;
    float prezzo;
    string editore;
    string genere;
    int numPagine;
    string lingua;
    string formato;
    string copertina;
}Ebook;
 
typedef struct
{
    Ebook libro[N];
    int nLibri;
    string nome;
    bool aperta;
    string sede;
    string logo;
}lib;

Is that even possible to write this struct, then close the program, reopen it, and read the same struct? I mean, strings are objects with dinamically changeable size.
?

Joined: 08/06/2010

I don't think so. A string object doesn't really contain the information, at heart it contains a pointer to the char array. So if you write it and read it back in, you end up with a bunch of dangling pointers that don't point to the same text.

The same is true for the "lib" struct. An array is at heart a pointer, so the array of books won't get copied.

It might be best not to write to a binary format. Most of your data is in a string format, so you could fairly easily write it to XML or a flatfile or such. That would also make the files portable, whereas binary files break if the endianness is different.

Another Planet finally has an official release! Download chapters 1 through 3 here! Thank you for waiting so long while I kept starting over.

Joined: 04/29/2011

The fact is that I already implemented writing in a flatfile and reading from it, and it works great. I need to write to binary only because my teacher said that.Sad

What do you think, if I change all strings in char[100] and then write every single vector to the file like this:

f.write(lib.nome,100);
f.write(lib.sede,100);
//other data
for(int i=0;i<100;i++)
{
  //ebooks data
}

Could that work?

Joined: 08/06/2010

That would work, just remember to pad with zero bytes (you can do this by memsetting it to 0 before each write to the array). It isn't really necessary but it will keep the array cleaner.

But it seems kind of weird that your teacher would ask you to do that. The purpose of binary files is to store binary data in an efficient way, but your structs have almost no binary data in them. Most of it is text.

Another Planet finally has an official release! Download chapters 1 through 3 here! Thank you for waiting so long while I kept starting over.

Joined: 04/29/2011

Thanks for help!

P.S. My teacher is kinda weird in these things. I dunno why he decided to use binary files. Everybody in my class are mad because of this.

Joined: 08/06/2010

Yes, my C++ teacher was a bit weird as well. Little micro-optimizations (z+z is faster than z*2) were always very important in that class.

Another Planet finally has an official release! Download chapters 1 through 3 here! Thank you for waiting so long while I kept starting over.

Joined: 07/05/2011

Binary files are small in size and hard to modify.
z+z is two or three times faster than z*2 if I recall correctly. So I don't think that is little micro-optimizations.

P.S. And z<<3 is faster than z*8 too. Tongue

Joined: 08/06/2010

True, but it's such a small change that it won't really matter in a student's class exercise. None of our programs were very optimized, and mine included several places where it intentionally slept the program to make the output look cooler. Tongue

Another Planet finally has an official release! Download chapters 1 through 3 here! Thank you for waiting so long while I kept starting over.

Joined: 04/29/2011

Still something not working. Here's a zip with my program. The executable and the source code are in the "Cartella Operativa del programma" folder. Its a bit messy. Can you look for CaricaBin and SalvaBin functions and see what's wrong? Thanks.

Joined: 09/01/2009

We've got our own stuff to do, rather than just fixing your program...
Paste the relevant parts of the source (not all of it) here, and explain what you're trying to do and what it's doing wrong. We don't really have time to dig through an entire program.

Joined: 04/29/2011

Well, I can say that I already finished and found the problem myself. Thanks again for help.

@AP
The solution I found was writing first the string's length and then the string itself. Then, it reads the length and the string of that length.

Joined: 08/06/2010

That works. Nice job fixing it.

Another Planet finally has an official release! Download chapters 1 through 3 here! Thank you for waiting so long while I kept starting over.

Joined: 09/01/2009

Yeah, sorry. I was going to suggest that, but typing on my iPod is so slow. Glad you figured it out, though!

Also, I think technically one-dimensional arrays within structs are read/written correctly, since that's what I did for some of the structures in liTools. Technically, though, reading/writing structures as a whole is a bad idea, since different compilers may handle padding differently. A friend of mine told me this, and I never ran into any issues with liTools, though, so I dunno.

tl;dr Good job, movildima! Glad you got it all sorted.