简体   繁体   中英

Ifstream read function doesn't load into vector

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.

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.

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 Device s 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 Device s.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM