writing string variable in binary file

I am confused in the technique used to write string data in binary file. If we write integer data in binary file instead, an example code used is:

1
2
 int score=55;
 myfile.write(reinterpret_cast<char*>(&score),sizeof(score));

here we convert the integer variable 'score' to char type and pass the address. but when working with string, why can't we do this:

1
2
 string name="John Doell";
 myfile.write(reinterpret_cast<char*>(&name),sizeof(name));


if the answer is regarding size of string, for eg, if you say: "John Doell" has 10 character=10 bytes, which is inconsistent with sizeof(name)(second arguement) which is of 4 bytes, so that the only 4 characters of "name" variable i.e. "John", would be written in the binary file. that is why we need to record the length of the string in the actually used method.

But then,regardless, of the length of the string, the variable "name" would still be of 4 bytes, isn't it? as in, here
int a=123456789;, even if "123456789" has 9 characters=9bytes, while writing into binary file, it somehow manages to write this number in 4 byte variable 'a'. so why can't the same happen while writing string in binary file.


or is this not your answer and i just wasted 2 paragraphs and lot of time describing this. i wrote this because i had been thinking about this approach for quite some time.

if you did not get the above two bulky paragraphy, please ignore it. any help would be appreciated.
Last edited on
1
2
 string name="John Doell";
 myfile.write(name.c_str(), name.size());


A std::string is not a char array. You cannot simply cast a string object of class type to a pointer of char type.
Does this help?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#include <cstring>
#include <iostream>
#include <fstream>
#include <string>

struct player_data
{
  std::string name;
  int score;
};

int main()
{

  std::ofstream savefile("score.dat", std::ios_base::binary);
  if(savefile.good())
  {
    player_data Player1;
    Player1.name = "John Doell";
    Player1.score = 55;
    savefile.write(Player1.name.c_str(),Player1.name.size()); // write string to binary file
    savefile.write("\0",sizeof(char)); // null end string for easier reading
    savefile.write(reinterpret_cast<char*>(&Player1.score),sizeof(Player1.score)); // write int to binary file
    savefile.close();
  }

  std::ifstream loadfile("score.dat", std::ios_base::binary);
  if(loadfile.good())
  {
    player_data Player1;
    std::getline(loadfile,Player1.name,'\0'); // get player name (remember we null ternimated in binary)
    loadfile.read((char*)&Player1.score,sizeof(Player1.score)); // read int bytes
    std::cout << "Player1 name: " << Player1.name << std::endl;
    std::cout << "Player1 score: " << Player1.score << std::endl;
  }

  return 0;
}
Last edited on
A string object contains a pointer to the characters, something like this:
1
2
3
4
5
class string
{
	char* buffer;
	// it also contains other variables for size and other things ...
};

If you write the string using the method you describe above only the pointer (and other member variables of string) will be written to the file. The data that the pointer points to is not written to the file, so next time you run your program and try to read the pointer back from the file it will give you an invalid pointer that is not safe to use.

What you could do is that you first write the size of the string to the file and then write the characters of the string. You can use the c_str() member function to get a pointer to the characters of the string.
1
2
myfile.write( // ... first write the length of the string
myfile.write(name.c_str(), name.length()); // then write the string characters 

Or you could write it as a null-terminated string and use std::getline to read the string back again.
1
2
3
// Write string.
// Note the +1 makes it output the null-character '\0' that marks the end of every string.
myfile.write(name.c_str(), name.length() + 1); 
1
2
// Read string.
getline(myfile, name, '\0');


123456789 is an int. If you convert it a string "123456789" then it will have 9 characters (10 characters if you count the null character) but then it's no longer an int.
Last edited on
here we convert the integer variable 'score' to char type

The code does not convert the integer variable to a char type. It gets the address of the int (an int*) and casts that (address) to a char*.

write() just needs to know where the data is and how big it is, and as char is the smallest type it makes sense to use it as the 'block' size.

int a=123456789;

In int a=123456789; the 123456789 is a decimal string representing the value. The compiler parses that to a binary value.

Binary is a pain for humans to read, but it does map directly to heaxadecimal (4 bits to a nybble), so you can write the value the computer deals with (assuming a 32-bit int) as 07 5B CD 15 (where I've put a spaces between the bytes (2 nybbles each) and am not worrying about endian issues.)

But then,regardless, of the length of the string, the variable "name" would still be of 4 bytes, isn't it?

As PanGalactic said, a std::string is not a char array. I simple version of a string is usually a length and a pointer to the allocated data (which is a char array.).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class string {
private:
    size_t size;
    char* data;
public:
    string();
    // etc
    const char* c_str() const {
        return data;
    }
    size_t size() const {
        return size;
    }
    // etc.
};


So when you save one of these variables you are saving the values of the size and pointer, not the string being pointed to which is elsewhere in memory.

Andy
Last edited on
thanks everyone. @Texan40 using getline to get string using '\0' was a new trick for me. @Peter87 a great clarification. right on the problem. btw what does buffer really mean though, see it used around quite a bit but don't really understand it.

@everyone_above(not a username ;) ) while working with binary files, rather than writing more code to properly view it, can we use some program to view what is written in the file, in readable format ofcourse. like hex editor, is it? i downloaded the program but can't make it show contents in readable format, not just string but also integers we wrote? a little help :)
Last edited on
Topic archived. No new replies allowed.