Reputation: 327
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.
Upvotes: 1
Views: 5726
Reputation: 38919
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);
Upvotes: 4