Home > Back-end >  Why is std::ifstream closing by itself?
Why is std::ifstream closing by itself?

Time:11-01

I'm reading an ascii file this way:name1|name2|name3|name4|name5|name6|name7||||||||||name8|||name9 It consists in a bunch of names separated by the '|' char, some of the slots are empty. I'm using the following code to read the list of names:

#include <iostream>
#include <fstream>
#include <vector>
#include <string>

int main() {
    std::ifstream File;
    File.open("File.txt");
    if (!File.is_open())
        return -1;

    std::vector<std::string> Names;
    char Buffer[0xff];
    while (!File.getline(Buffer,16,'|').eof()) {
        if (strlen(Buffer) == 0)
            break;
        Names.push_back(Buffer);

        std::cout << strerror(File.rdstate()) << std::endl;
    }

    return 0;
}

It is working as it should, it reads a name each time, but for some reason if it hits the char count on the second argument of File.getline() and does not find the delimiting char, it closes itself. This is the console output I've got after running this code on a file with a big name:

File: File.txt
Ana|Bjarne Stroustrup|Alex

Console:
No error
No such file or directory

It reads the first name on the list successfully, but when it tries to read the second name, it doesn't hit the delimiting char, and for some reason it leads to the file closing by itself. I hope someone can explain to me why does this happen.

CodePudding user response:

You could use the below shown program to add names from your File.txt to the std::vector:

#include <iostream>
#include <vector>
#include <string>
#include <fstream>
int main()
{   
    std::ifstream inputFile("File.txt");
    
    std::string wordName;
    
    std::vector<std::string> Names;
    if(inputFile)
    {
        while(getline(inputFile, wordName, '|'))
        {
            if((wordName.size()!=0))
            {
                Names.push_back(wordName);
            }
        }
    }
    else 
    {
        std::cout<<"File could not be opened"<<std::endl;
    }
    
    inputFile.close();
    
    //lets check/confirm if our vector contains all the names correct names 
    for(const std::string &name: Names)
    {
        std::cout<<name<<std::endl;
    }
    return 0;
}

The output of the above program can be seen here.

CodePudding user response:

The expression strerror(File.rdstate()) is not meaningful. The expression File.rdstate() returns an integer which represents the bits of the state flags of the stream. This is not an error code. However, the function strerror expects an error code.

Therefore, calling strerror(errno) or perror(nullptr) may be more meaningful, in general. But in this case, both just return or print "No Error".

In your question, you wrote:

It reads the first name on the list successfully, but when it tries to read the second name, it doesn't hit the delimiting char, and for some reason it leads to the file closing by itself. I hope someone can explain to me why does this happen.

The file does not close. The error message

No such file or directory

that you are receiving is misleading. It is a result of your incorrect usage of the function strerror, as described above.

What happens is that if getline is unable to read the deliminating character, it causes the failbit to be set. Due to the stream being in a failed state, the next function call of getline in the next loop iteration immediately fails without attempting to extract any characters. This causes the if statement

if (strlen(Buffer) == 0)

to be true, causing the loop to be aborted.

  • Related