g-217
g-217

Reputation: 2210

problems with seekg after getlines[which exhausts file] on ifstream

I am trying to write a program to print last line of file, and I came up with following. Where I am doing SEEKs in the file, but this code runs in an infinite loop. If I comment out (1) and enable (2), code works fine. I wasn't able to figure out the reason.

#include <iostream>
#include <fstream>

int main()
{
    std::string line;
    int count = 0;
    long int seek_length = -1l;// should be -100l
    std::ifstream ifile("D:\\cprog\\test.csv");// --(1)
    while(true){
        seek_length *= 2;
        count = 0;
        //std::ifstream ifile("D:\\cprog\\test.csv"); //-- (2)
        ifile.seekg(seek_length, std::ios_base::end);
        while(std::getline(ifile,line)){
            ++count;
        }
        if(count > 1)
            break;
    }
    std::cout << line << '\n';
}

Compiler: g++ (GCC) 4.9.2 (MINGW)

Upvotes: 3

Views: 190

Answers (2)

g-217
g-217

Reputation: 2210

Final working code is following, the problem can be solved in one of the following ways.

#include <iostream>
#include <fstream>

int main()
{
    std::string line;
    int count = 0;
    long int seek_length = -100l;
    std::ifstream ifile("D:\\cprog\\test.csv");
#if 0
    while(true){
        seek_length *= 2;
        count = 0;
        ifile.seekg(seek_length, std::ios_base::end);
        if( ifile.tellg() < 0 ){
            ifile.clear();
            ifile.seekg(0l, std::ios_base::beg);
            while(std::getline(ifile,line));
            break;
        }
        else
        {
           while(std::getline(ifile,line)){
              ++count;
           }
            if(count > 1)
                break;
        }
        ifile.clear();
    }
#else
    char ch;
    ifile.seekg(0l, std::ios_base::end);
    do
    {
        ch = ifile.peek();
        ifile.seekg(-1l, std::ios_base::cur);
        std::cout << ch <<'~' << ifile.tellg() <<'\n';
    }while(ch != '\n' && ifile.tellg() > -1 );
    if(ifile.tellg() < 0 )
        ifile.seekg(0l, std::ios_base::beg);
    else
        ifile.seekg(2l, std::ios_base::cur);
    ifile.clear();
    std::getline(ifile,line);
#endif
    if(line.empty())
        std::cout<<"------- EMPTY LINE -----\n";
    else std::cout << line << '\n';
}

Upvotes: 0

paddy
paddy

Reputation: 63481

You need to clear the error state on your stream before reading again:

ifile.clear();

Otherwise, the first time it encounters EOF, the stream gets into an error state and all subsequent reads will fail.

Beware that if you do this and your file only contains 1 (or 0) lines, your code in its present form will loop forever.

Upvotes: 3

Related Questions