1

I want to write my array structure in to a binary file.

My structure

typedef struct student{
     char name[15];
     vector<int> grade;
}arr_stu;

I can write and read back my data if I write and read in the same program; but if I create another program for read data only and put the binary file, it does not work because the vector grade is null.

size = 0;
unable to read from memory

Program to write array structure to file

int main()
{
arr_stu stu[100];

for (size_t i = 0; i < 100; i++)
{
    strcpy(stu[i].name, randomName());
    for (size_t j = 0; j < 10; j++)
    {
        stu[i].grade.push_back(randomGrade());
    }
}   

ofstream outbal("class", ios::out | ios::binary);
if (!outbal) {
    cout << "Cannot open file.\n";
    return 1;
}

outbal.write((char *)&stu, sizeof(stu));
outbal.close();
}

Program to read array structure to file

int main(){

    feature_struc stu[100];

    ifstream inbal("class", ios::in | ios::binary);
if (!inbal) {
    cout << "Cannot open file.\n";
    return 1;
}

inbal.read((char *)&stu, sizeof(stu));

for (size_t idx = 0; idx < 100; idx++)
{
    cout << "Name :  " << stu[idx].name << endl;   
    for (size_t index = 0; index < 10; index++)
    {
        cout << endl << "test: " << stu[idx].grade[index] << endl;
    }
}
inbal.close();
return 0;
}

For me it seems like the use of vector pose the problem, The reason that if we combine the two in one program it work well I think because vector is saved in the memory so it can still accessible.

Any suggestions?

2
  • You do not need the typedef struct..., and you should also be using more std::vector as well as std::string instead of arrays and C strings. Commented May 16, 2014 at 15:24
  • It's mandatory you use a binary file for this? Can't you use something like XML, YAML, JSON or even sqlite if you want to keep things in binary style? Commented May 16, 2014 at 16:03

3 Answers 3

4

You cannot serialize a vector like that. The write and read functions access the memory at the given address directly. Since vector is a complex class type only parts of its data content are stored sequentially at its base address. Other parts (heap allocated memory etc) are located elsewhere. The simplest solution would be to write the length of the vector to the file followed by each of the values. You have to loop over the vector elements to accomplish that.

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

7 Comments

are there any solution not to loop over all the vector elements in case we have large contents?
The vector implementation in C++11 provides a data member function returning a pointer to the allocated memory directly which could be used for serializing the contents. Previous standards do not provide this function so you can't avoid iterating over the contents.
You may also want to take a look at the boost::serialization library which implements generic patterns for serializing objects
@sayvortana If you have a vector v of POD members (type T e.g. T==int) you can directly access the full data by const T* p=&v[0] in pre-C++11. Furthermore, you know the size by sizeof(T)*v.size(). Therefore, writing without looping is possible. More complex data types T are problematic.
Citation from Section [vector.overview] of the C++ spec.: The elements of a vector are stored contiguously, meaning that if v is a vector<T, Allocator> where T is some type other than bool, then it obeys the identity &v[n] == &v[0] + n for all 0 <= n < v.size(). BTW, writing the whole data block into a vector (with sufficient space) is analogously possible.
|
1

outbal.write((char *)&stu, sizeof(stu));

The sizeof is a compile-time constant. In other words, it never changes. If the vector contained 1, 10, 1000, or 1,000,000 items, you're writing the same number of bytes to the file. So this way of writing to the file is totally wrong.

The struct that you're writing is non-POD due to the vector being a non-POD type. This means you can't just treat it as a set of bytes that you can copy from or to. If you want further proof, open the file you created in any editor. Can you see the data from the vector in that file? What you will see is more than likely, gibberish.

To write the data to the file, you have to properly serialize the data, meaning you have to write the data to a file, not the struct itself. You write the data in a way so that when you read the data back, you can recreate the struct. Ultimately, this means you have to

  1. Write the name to the file, and possibly the number of bytes the name consists of.
  2. Write the number of items in the vector
  3. Write each vector item to the file.

If not this, then some way where you can distinctly figure out the name and the vector's data from the file so that your code to read the data parses the file correctly and recreates the struct.

1 Comment

You can't write PODs this way, either, and expect to be able to reread them.
0

What is the format of the binary file? Basically, you have to define the format, and then convert each element to and from that format. You can never just dump the bits of an internal representation to disk and expect to be able to read it back. (The fact that you need a reinterpret_cast to call ostream::write on your object should tell you something.)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.