1

I have created student data to be stored in a binary file but this file is completely broken.

What am I doing wrong?

there was no problem with the text file stored in the notepad.

now after entering after starting the program, it only writes this:

& Ô LC_CTYPE = C; LC_M0 & Ô RIC = C; LC_TIME = C

Is there someone able to help me with this? Have a nice day:)

    #include <iostream>
    #include <fstream>
    #include <string>
    #include <cstdlib>
    
    
    
    using namespace std;
    
    
    
    struct Student{
        string imie;
        string nazwisko;
        int nrAlbumu;
        int wiek;
        float srOcen;
    } dane;
    
    
    
    
    int main(){
    
    
    
    Student dane;
    
    cout << "Podaj imie:" << endl;
    cin >> dane.imie;
    cout << "Podaj nazwisko:" << endl;
    cin >> dane.nazwisko;
    cout << "Podaj nrAlbumu:" << endl;
    cin >> dane.nrAlbumu;
    cout << "Podaj wiek:" << endl;
    cin >> dane.wiek;
    cout << "Podaj srednia ocen:" << endl;
    cin >> dane.srOcen;
    
    
    cout << "Student " << dane.imie  <<" "<< dane.nazwisko << " o numerze albumu: " << dane.nrAlbumu << " ma lat " << dane.wiek << " ma srednia ocen rowna: " << dane.srOcen << endl;
    
    
//-------writing to the file starts here-------------------------

    ofstream ofs("dane.bin", ios::binary);
    
    Student* student = new Student;
    
    student->imie;
    student->nazwisko;
    student->nrAlbumu;
    student->wiek;
    student->srOcen;
    
    ofs.write((char*)(student), sizeof(Student));
    ofs.close();
    
     delete student;
    
 //-------------reading starts here ---------------------------
    
    ifstream ifs("dane.bin", ios::binary);
    
    char* temp = new char[sizeof(Student)];
    ifs.read(temp, sizeof(Student));
    
    Student* student2 = (Student*)(temp);
    
    cout << "Student " << dane.imie  <<" "<< dane.nazwisko << " o numerze albumu: " << dane.nrAlbumu << " oraz ma lat " << dane.wiek << " ma srednia ocen rowna: " << dane.srOcen <<"  Potwierdzenie do zapisu i odczytu!" << endl;
    
    delete student;
    
    
    
    
        return 0;
    }
12
  • ofs.write((char*)(student), sizeof(Student)); -- This will never work. Types that are not trivially copyable cannot be written to binary files like this. You need to serialize the object, not just write raw bytes to a binary file. Commented Nov 17, 2020 at 8:26
  • in what sense should I understand? trivially copyable? I do not understand Commented Nov 17, 2020 at 8:30
  • The Student object contains std::string. That is an object that is not trivially-copyable, thus the Student class is not trivially-copyable. If you want more proof, what does sizeof do? What value does it return? The sizeof is a compile-time value. Now let's say that std::string has a size() of 1000 characters. The sizeof had no idea how many characters at runtime the std::string will have. Thus that entire line makes no sense and will not work. If you std::cout << sizeof(Student); what value do you get? I bet it isn't 1000. Commented Nov 17, 2020 at 8:32
  • See this and this. Basically you write the data to a file, not the object. Then when reading, you read the data and then recreate the object from the data. Commented Nov 17, 2020 at 8:35
  • Here is a quick program explaining the problem Commented Nov 17, 2020 at 8:47

1 Answer 1

0

The Student object contains std::string members. That is an object that is not trivially-copyable, thus the Student class is not trivially-copyable, so you cannot simply read and write this type to a binary file by merely copying the bytes to and from the file.

If you want more proof, what does sizeof do? What value does it return? The sizeof is a compile-time value. Now let's say that std::string has a size() of 1000 characters. The sizeof had no idea how many characters at runtime the std::string will have. Thus that entire line makes no sense and will not work.

If you did the following, given that there would be 1000 characters in one of the std::string members:

std::cout << sizeof(Student);

what value do you get? I bet it isn't 1000 or greater.

Here is a quick program illustrating the problem:

#include <type_traits>
#include <string>
#include <iostream>

struct Student{
    std::string imie;
    std::string nazwisko;
    int nrAlbumu;
    int wiek;
    float srOcen;
};

struct Student2{
    char imie[20];
    char nazwisko[20];
    int nrAlbumu;
    int wiek;
    float srOcen;
};

int main()
{
    Student s;
    s.imie = std::string(1000, ' ');
    std::cout << "The number of characters is: " << s.imie.size() << "\n";
    std::cout << "The sizeof(Student) is: " << sizeof(s) << "\n";
    std::cout << "Is Student trivially copyable? " << (std::is_trivially_copyable<Student>()?"Yes":"No") << "\n";
    std::cout << "Is Student2 trivially copyable? " << (std::is_trivially_copyable<Student2>()?"Yes":"No") << "\n";
}

Output:

The number of characters is: 1000
The sizeof(Student) is: 80
Is Student trivially copyable? No
Is Student2 trivially copyable? Yes

Note that if you used char arrays instead of std::string, then the struct becomes trivially copyable and then can be used to write to a binary file in the way you're currently doing it now.

However the disadvantage is that you are limited to the number of characters (20 in my example). If you still want to use std::string, you have to write the struct in individual pieces, taking care of each std::string accordingly as specified by this answer.

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.