Question

I'm somewhat new to programming, so I'm not sure how to search for this problem, and I know I asked 2 other questions about this, but I can't seem to make it work.

I got a problem, where I have a vector:

vector<Device*> Devicelist_;

Whhere I try to load Devices into using this function (I already made a Save-function, which works):

bool Devicelist::LoadFromFile() //Opdaterer vector<Device> fra fil
{
    ifstream LoadFile("Devices.dat", ios::in | ios::binary);

    if (!LoadFile)
    {
        cerr << "File could not be opened." << endl;
        return false;
    }

    LoadFile.seekg(0, ios::end);
    int numberOfDevices = LoadFile.tellg() / sizeof(Device);

    for (int i = 0; i < numberOfDevices; i++)
    {   
        Devicelist_.push_back(new Device);
        LoadFile.read(reinterpret_cast<char *>(Devicelist_[i]), sizeof(Device));
    }

    cout << Devicelist_[0]->getName() << endl;

    LoadFile.close();
    return true;
}

The problem is that LoadFile.read() does not load any Devices into the devicelist.

Can you see what my problem is? Thanks in advance.

Was it helpful?

Solution

Your problem is actually really simple. You forgot to reset your get position:

LoadFile.seekg(0, ios::end);
int numberOfDevices = LoadFile.tellg() / sizeof(Device);

for (int i = 0; i < numberOfDevices; i++)

should be

LoadFile.seekg(0, ios::end);
int numberOfDevices = LoadFile.tellg() / sizeof(Device);
LoadFile.seekg(0L, ios::beg);
for (int i = 0; i < numberOfDevices; i++)

An alternative to finding the number is using stat:

#include <sys/stat.h>
int getNumberOfDevices(char *filename)
{
    struct stat st;
    return st.st_size / sizeof(Device);
}

or, if you wanted to avoid stat, you could do something like this:

bool Devicelist::LoadFromFile() //Opdaterer vector<Device> fra fil
{
    ifstream LoadFile("Devices.dat", ios::in | ios::binary);
    if (!LoadFile)
    {
        cerr << "File could not be opened." << endl;
        return false;
    }
    int numberOfDevices = 0;
    while (true)
    {   
        Device *tmp = new device; 
        LoadFile.read(reinterpret_cast<char *>(tmp), sizeof(Device));
        if (LoadFile.good()) //we successfully read one
        {
            ++numberOfDevices;
            Devicelist_.push_back(tmp);
        }
        else break; //get out of the infinite loop
    }
    cout << Devicelist_[0]->getName() << endl;
    LoadFile.close();
    return true;
}

This way, it reads all of them, without messing around with positions, and keeps a count when it is finished.

OTHER TIPS

This line

LoadFile.seekg(0, ios::end);

puts the file at the end of the file. You need to put it back at the start by

LoadFile.seekg(0, ios::beg);

Update

You can make the code simpler by saving the number of Devices at the top of the file. Then, you can use:

int numberOfDevices = 0;
LoadFile.read(&numberOfDevies, sizeof(int));

for (int i = 0; i < numberOfDevices; i++)

There won't be any need to get the size of the file to deduce the number of Devices.

The other alternative is the one suggested by @phyrrus9 where you keep reading the Devices until there are no more Devices to read from the file.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top