Search code examples
c++filefstream

Read a line of a file c++


I'm just trying to use the fstream library and I wanna read a given row. I thought this, but I don't know if is the most efficient way.

#include <iostream>
#include <fstream>
using namespace std;
int main(){
    int x;
    fstream input2;
    string line;
    int countLine = 0;
    input2.open("theinput.txt");
    if(input2.is_open());
        while(getline(input2,line)){
            countLine++;
            if (countLine==1){ //1 is the lane I want to read.
                cout<<line<<endl;
            }

        }
    }

}

Is there another way?


Solution

  • This does not appear to be the most efficient code, no.

    In particular, you're currently reading the entire input file even though you only care about one line of the file. Unfortunately, doing a good job of skipping a line is somewhat difficult. Quite a few people recommend using code like:

    your_stream.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
    

    ...for this job. This can work, but has a couple of shortcomings. First and foremost, if you try to use it on a non-text file (especially one that doesn't contain new-lines) it can waste inordinate amounts of time reading an entire huge file, long after you've read enough that you would normally realize that there must be a problem. For example, if you're reading a "line", that's a pretty good indication that you're expecting a text file, and you can pretty easily set a much lower limit on how long that first line could reasonably be, such as (say) a megabyte, and usually quite a lot less than that.

    You also usually want to detect whether it stopped reading because it reached that maximum, or because it got to the end of the line. Skipping a line "succeeded" only if a new-line was encountered before reaching the specified maximum. To do that, you can use gcount() to compare against the maximum you specified. If you stopped reading because you reached the specified maximum, you typically want to stop processing that file (and log the error, print out an error message, etc.)

    With that in mind, we might write code like this:

    bool skip_line(std::istream &in) { 
        size_t max = 0xfffff;
    
        in.ignore(max, '\n');
        return in.gcount() < max;
    }
    

    Depending on the situation, you might prefer to pass the maximum line size as a parameter (probably with a default) instead:

    bool skip_line(std::istream &in, size_t max = 0xfffff) { 
        // skip definition of `max`, remainder identical
    

    With this, you can skip up to a megabyte by default, but if you want to specify a different maximum, you can do so quite easily.

    Either way, with that defined, the remainder becomes fairly trivial, something like this:

    int main(){  
        std::ifstream in("theinput.txt");
    
        if (!skip_line(in)) {
            std::cerr << "Error reading file\n";
            return EXIT_FAILURE;
        }
    
        // copy the second line:
        std::string line;
        if (std::getline(in, line))
            std::cout << line;
    }
    

    Of course, if you want to skip more than one line, you can do that pretty easily as well by putting the call to skip_line in a loop--but note that you still usually want to test the result from it, and break the loop (and log the error) if it fails. You don't usually want something like:

    for (int i=0; i<lines_to_skip; i++)
        skip_line(in);
    

    With this, you'd lose one of the basic benefits of assuring that your input really is what you expected, and you're not producing garbage.