43

How can I count lines using the standard classes, fstream and ifstream?

tshepang
  • 12,111
  • 21
  • 91
  • 136
malhobayyeb
  • 2,725
  • 11
  • 57
  • 91
  • 1
    Whats the deinition of a `line` - does the content between the last linebreak and the end of file count? what if there was a linebreak directly followed by eof. – Greg Domjan Jun 18 '10 at 22:28

8 Answers8

127

How about this :-

  std::ifstream inFile("file"); 
  std::count(std::istreambuf_iterator<char>(inFile), 
             std::istreambuf_iterator<char>(), '\n');
Abhay
  • 7,092
  • 3
  • 36
  • 50
  • 1
    Just remembered something, What if the last line doesn't have a \n? – fingerprint211b Jun 18 '10 at 20:42
  • 8
    @fingerprint211b: Add one to the result :-) There is always this tradeoff whether u have a newline at the end of file. – Abhay Jun 18 '10 at 20:44
  • 2
    @fingerprint211b: Then there is one less line. Just because the last line is blank does not mean it's any different than any other line. – Billy ONeal Jun 18 '10 at 20:44
  • @wheaties: I also think think this is a faster way of counting lines in file if not the fastest. If you are reading lines, the system library (be it fgets or std::readline) will copy the data to *your* buffer; but an optimal solution will access the data in the buffer where it is read from the system, like memory mapping. So the truly optimal solution by the library could be to create a mmap_streambuf to mmap the file. A count_lines method would then just iterate over it there would never be a need to copy the data at all. – Abhay Jun 18 '10 at 20:56
  • I cannot find "std:count" I just included , and . – malhobayyeb Jun 18 '10 at 21:08
  • 3
    @MIH: A quick Google search would have told you that `std::count()` is in ``. – James McNellis Jun 18 '10 at 21:10
  • 4
    @MIH1406: `#include ` – Abhay Jun 18 '10 at 21:10
  • 1
    +1 for `istream` **buf** `_iterator`, as made famous by Item 29 of Effective STL! – Cubbi Jun 18 '10 at 22:46
  • I get the error `error: const struct std::basic_string, std::allocator >' has no member named 'str'` when I try to use this solution. Anyone know how to fix it? – synaptik Dec 01 '12 at 03:44
  • It looks like with `std:ifstream` you never have to close the file? – qed Nov 04 '13 at 13:43
  • @qed: See http://stackoverflow.com/questions/748014/do-i-need-to-manually-close-a-ifstream – Abhay Nov 04 '13 at 14:33
  • 1
    Pretty sure this solution only works if you assume the encoding is low ASCII, since you're parameterizing the type with `char`, so you're comparing one octet at a time rather than one actual character at a time. That said, it works for my use case, so +1 to you. :) – Parthian Shot Nov 04 '15 at 02:40
  • @ParthianShot: It will work for any of the ISO-8859 encodings, many Windows / DOS codepages, and UTF-8 as well (assuming the compiler encodes `'\n'` as `0x0a`). By no means perfect, but sufficient if you can assert the file is in one of those encodings. – DevSolar Apr 21 '16 at 07:23
  • This method will give an invalid line count (1 too few lines) if the file lacks a POSIX `eol` (e.g. a `'\n'` at the end of the last line of text) And since there is no buffer to check whether it contains valid text, there is no way to catch that condition. – David C. Rankin Mar 14 '19 at 21:30
  • @DavidC.Rankin I would argue that the result is always one two small. The POSIX thing is a red hearing. If the last character is a new line then there is another line that is empty at the end. How does an empty line at the end differ from an empty line anywhere else in the file? – Martin York Mar 15 '19 at 00:05
  • 3
    The point is this `size_t n = 0; while (getline (stream, string)) n++;` will accurately report the number of lines regardless whether the file has a POSIX `eof`. The `std::count` approach, as shown in this answer, will fail to count the final line -- even though text is present to read. A line count should be accurate regardless. The underbelly to the whole issue the why a significant minority of text-editors continue to write files with non-POSIX endings. `:)` – David C. Rankin Mar 15 '19 at 02:48
13

You read the file line by line. Count the number of lines you read.

Martin York
  • 257,169
  • 86
  • 333
  • 562
13

This is the correct version of Craig W. Wright's answer:

int numLines = 0;
ifstream in("file.txt");
std::string unused;
while ( std::getline(in, unused) )
   ++numLines;
Billy ONeal
  • 104,103
  • 58
  • 317
  • 552
  • std::getline(in, std::string()) - Binding a non-const reference to a temporary is not legal C++. – Pietro Apr 08 '13 at 14:16
2

kernel methods following @Abhay

A complete code I've done :

#include <fstream>

std::size_t count_line(std::istream &is) {
    // skip when is not open or got bad
    if (!is || is.bad()) { return 0; }
    // save state
    auto state_backup = is.rdstate();
    // clear state
    is.clear();
    auto pos_backup = is.tellg();

    is.seekg(0);
    size_t line_cnt;
    size_t lf_cnt = std::count(std::istreambuf_iterator<char>(is), std::istreambuf_iterator<char>(), '\n');
    line_cnt = lf_cnt;
    // if the file is not end with '\n' , then line_cnt should plus 1
    // but we should check whether file empty firstly! or it will raise bug
    if (is.tellg() != 0) {
        is.unget();
        if (is.get() != '\n') { ++line_cnt; }
    }

    // recover state
    is.clear() ; // previous reading may set eofbit
    is.seekg(pos_backup);
    is.setstate(state_backup);

    return line_cnt;
}

it will not change the origin file stream state and including '\n'-miss situation processing for the last line.

Thanks @masoomyf for pointing my bug and I was too stupid to figure it out!

0
int aNumOfLines = 0;
ifstream aInputFile(iFileName); 

string aLineStr;
while (getline(aInputFile, aLineStr))
{
    if (!aLineStr.empty())
        aNumOfLines++;
}

return aNumOfLines;
Maria
  • 63
  • 1
  • 6
0

This works for me:

  std::ifstream fin{"source.txt"};
  std::count(std::istream_iterator<char>(fin >> std::noskipws), {}, '\n');
Adem Budak
  • 65
  • 4
-3

int numLines = 0;
ifstream in("file.txt");
//while ( ! in.eof() )
while ( in.good() )
{
   std::string line;
   std::getline(in, line);
   ++numLines;
}

There is a question of how you treat the very last line of the file if it does not end with a newline. Depending upon what you're doing you might want to count it and you might not. This code counts it.

See: http://www.cplusplus.com/reference/string/getline/

Craig Wright
  • 1,575
  • 1
  • 11
  • 19
  • 7
    `while ( ! in.eof() )` <--- NOOOOO! This will give garbage if there's any type of failure reading the file. Put `std::getline` as the condition of the while. – Billy ONeal Jun 18 '10 at 20:36
  • 3
    It's still invalid after your edit because if `std::getline` fails, you increment the line count, and don't check if it succeeded until after. Move `std::getline` into the condition of the while. – Billy ONeal Jun 18 '10 at 20:46
-15

Divide the file size by the average number of characters per line!

John
  • 3
  • 2
    How does one determine the average number of characters per line without reading the file? If your counting characters, you might as well just count the newlines instead; which kind of invalidates your answer. – Thomas Matthews Jun 19 '10 at 01:27
  • 3
    Awesome! This is exactly how 99.99% of the code I get from my predecessors is written! – Herwig Apr 07 '21 at 08:07
  • 1
    You deserve a Nobel prize for this solution. – Orif Milod Dec 03 '22 at 13:34