1

I have a custom class called Array. It stores the array of type T and a size integer.

Does this look right saving an array to file?

fout.write((char *)m_array, sizeof(T) * m_size);

How I'm storing it:

    bool save(const std::string &filename)
    {
        std::ofstream fout;

        // Open the file.
        fout.open(filename, std::ios::out | std::ios::binary);

        // Validate that the file is open.
        if (!fout.is_open())
            return false;

        // Write the size to file.
        fout << m_size << std::endl;  

        fout.write((char *)m_array, sizeof(T) * m_size);

        fout.close();

        return true;
    }

Load function:

    bool load(const std::string &filename)
    {
        std::ifstream fin;
        int size = 0;

        // Open the file.
        fin.open(filename, std::ios::in | std::ios::binary);

        // Validate that the file is open.
        if (!fin.is_open())
            return false;

        // Read the size from file.
        fin >> size;

        // Resize if needed
        if (size != m_size)
            resize(size); 

        fin.read((char *)m_array, sizeof(T) * m_size);

        fin.close();

        return true;
    }

The main file:

Array<int> a(10);

a.clear(); // set all values to 0. 

a[5] = 3; 

if (a.save("test.dat"))
    con.writeLine("Saved");

This gives the output values 0,0,0,0,0,0,3,0,0,0.

But on retrieval, using this:

fin.read((char *)m_array, sizeof(T) * m_size);

I'm getting 10,0,0,0,0,768,0,0,0,0.

What am I doing wrong? The second parameter says it wants the count, which would be sizeof(T) * m_size to me.

Update: The alternative is this on saving:

for (int i = 0; i < m_size; i++)
fout << m_array[i] << std::endl;

But I prefer the first method.

1
  • 1
    Add fin.get(); after fin >> size. Commented Jun 23, 2018 at 19:11

1 Answer 1

4

You're mixing formatted and unformatted writes to the stream. Rather than:

fout << m_size << std::endl;

You need to do:

fout.write(reinterpret_cast<char*>(&m_size), sizeof(m_size));

EDIT:
After seeing you're update you'll need to read, not with this:

fin >> size;

But with this:

fin.read(reinterpret_cast<char*>(&m_size), sizeof(m_size));

So it should be mentioned here that you're reinventing the wheel. As long as you're OK with this... None the less I think it's appropriate here for me to suggest using vector<T>. It would make your code more readable, less error prone, and potentially faster.

Given vector<int> a you can write to ofstream fout like this:

const auto a_size = size(a);

fout.write(reinterpret_cast<const char*>(&a_size), sizeof(a_size));
fout.write(reinterpret_cast<const char*>(data(a)), sizeof(decltype(a)::value_type) * a_size);

Given ifstream fin, you can read like this:

size_t a_size;

fin.read(reinterpret_cast<char*>(&a_size), sizeof(a_size));
a.resize(a_size);
fin.read(reinterpret_cast<char*>(data(a)), sizeof(decltype(a)::value_type) * a_size);

Live Example

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

5 Comments

I'm getting ten -842150451's on retrieval using this. When reading in the size, do I need to do the same reinterpret_cast?
Adding this for both reading and writing gives me the correct result.
You can't read directly into m_size. If the Array was a different size, bad will happen because you won't know if you need to resize it. You'll still need to read into the temporary size.
Yes, I have this, and optional for the poster to include a temp local size instead of using the member variable. Thanks for the answer, @JonathanMee.
@user4581301 As long as he reads it in and then immediately uses it to resize his container that's fine.

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.