Ifstream read function doesn't load into vecto

2019-02-27 23:47发布

问题:

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.

回答1:

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.



回答2:

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.