0

I'm trying to read a .bin file that I have made that include two integers and one string inside a struct. The int shows fine, but somehow the string output shows weird symbols.

This is the write script:

#include <iostream>
#include <fstream>
#include <string>

using namespace std;

struct student{
    int no;
    string name;
    int score;
};

int main(){
    fstream myFile;
    myFile.open("data.bin", ios::trunc | ios::out | ios::in | ios::binary);

    student jay, brad;

    jay.no = 100;
    jay.name = "Jay";
    jay.score = 95;

    brad.no = 200;
    brad.name = "Brad";
    brad.score = 83;

    myFile.write(reinterpret_cast<char*>(&jay),sizeof(student));
    myFile.write(reinterpret_cast<char*>(&brad),sizeof(student));

    myFile.close();

    cin.get();
    return 0;
}

and this is the read script:

#include <iostream>
#include <fstream>
#include <string>

using namespace std;

struct student{
    int no;
    string name;
    int score;
};

int main(){
    fstream myFile;
    myFile.open("data.bin", ios::in | ios::binary);

    student readFile;

    myFile.seekp(1*sizeOf(student)); //I use this because I want only specific position 
                                     //to be shown, for example I put 1 to show only Brad

    myFile.read(reinterpret_cast<char*>(&readFile),sizeof(student));
    cout << "No   : " << readFile.no << endl;
    cout << "Name : " << readFile.name << endl;
    cout << "Score: " << readFile.score << endl;

    myFile.close();

    cin.get();
    return 0;
}

The result would be like this:

No   : 200
Name : ñ∩K 
Score: 83

The string showed "ñ∩K" instead of "Brad". I tried not to use seekp, and using read twice:

    myFile.read(reinterpret_cast<char*>(&readFile),sizeof(student));
    cout << "No   : " << readFile.no << endl;
    cout << "Name : " << readFile.name << endl;
    cout << "Score: " << readFile.score << endl;

    myFile.read(reinterpret_cast<char*>(&readFile),sizeof(student));
    cout << "No   : " << readFile.no << endl;
    cout << "Name : " << readFile.name << endl;
    cout << "Score: " << readFile.score << endl;

The result would be:

No   : 100
Name : Jay
Score: 95

No   : 200
Name : ε@ 
Score: 83

As you can see, the first position shows "Jay" fine but the next one is not. Any idea what went wrong? I'm new to C++.

halfer
  • 19,824
  • 17
  • 99
  • 186
Fariz R
  • 5
  • 4
  • 1
    You cannot `write` a `std::string`. `string` is too complicated a structure for a simple binary dump. You will have to (Incoming search term!) serialize. – user4581301 Mar 28 '19 at 04:29
  • 1
    The binary storage of a `string` contains size info, a ptr to the heap where the sring contents are, among other things. There is something called small string optimization that can eliminate the heap storage and puts small strings in the same block. Don't save strings as binary objects since you can't read them back. – doug Mar 28 '19 at 04:30
  • It is theoretically possible, depending on the C++ standard library, that particularly short strings (around 16 to 23 characters) could be written this way because of what's called the small-string optimization, but you absolutely should not count on that. – Daniel H Mar 28 '19 at 04:49
  • 1
    You may find this question helpful: https://stackoverflow.com/questions/7046244/serializing-a-class-which-contains-a-stdstring – Frax Mar 28 '19 at 05:07

1 Answers1

3

What you're writing to the file is not a string, but the internal structure of the std::string object. Likely that's a pointer. When you read it back in, the pointer will be pointing to something that isn't valid. You're lucky to get any output at all rather than a crash, or demons flying from your nostrils.

Mark Ransom
  • 299,747
  • 42
  • 398
  • 622
  • 3
    For the reference: [nasal demons](http://catb.org/jargon/html/N/nasal-demons.html) is a jargon term for [undefined behavior](https://en.m.wikipedia.org/wiki/Undefined_behavior). The meaning is that program doing illegal stuff (like reading random memory) may produce any kind of weird and unpredicted effect. – Frax Mar 28 '19 at 04:51