AngryDev
AngryDev

Reputation: 189

Printing rdbuf() to console works, but getline fails

I'm having a strange issue where printing to the console using rdbuf() from a file using ifstream works, but the string parameter inside of getline never returns a value, and thus fails to print to the console in a for loop. I was trying to add the lines in the file to a vector for processing and I know there's other methods to do that, but I'm confused as to why the getline would fail. The file consists of the following text:

One
Two
Three
Four

Code below.

    std::string path = "C:/testfile.txt";      

    std::ifstream File(path);
    File.open(path);
    std::string placeholder;

    if (!File.is_open())
    {
        std::cout << "WARNING: Unable to open file" << std::endl;
    }
    else
    {
        //This prints to the console correctly;
        std::filebuf* stream = File.rdbuf();
        std::cout << stream << std::endl;
        //------------------------------------

        //This fails because placeholder is always "" and the loop doesn't run.
        for (std::string output; std::getline(File, placeholder);) 
        {
            std::cout << output << std::endl;
        }

        File.close();
    }

Upvotes: 0

Views: 222

Answers (1)

Some programmer dude
Some programmer dude

Reputation: 409356

File.rdbuf() doesn't return a copy of the buffer for the stream, it returns a pointer to the actual in-use buffer for the stream.

That means when you do

 std::cout << stream << std::endl;

you exhaust the actual file stream, and put it at the end of file. Which means the std::getline call will fail.

You need to reset the stream and seek back to the beginning again after the output.


The problem with opening the file twice is that the second attempt will fail, meaning that failbit will be set. And that means all future operations on the stream itself (but not the buffer) will fail.

See e.g. this open reference for details.

The obvious solution is of course to not open the file twice, but if there's a risk that it might happen then always clear the stream status after calling open.

Upvotes: 3

Related Questions