How to get number of lines with SplFileObject?

11,588

Solution 1

Why not simply use file handlers and do like in this question? Its simple, fast and very efficient.

If you absolutely must use spl, you can do it like this

$file = new SplFileObject("/path/to/file.txt");
$i = 0;
while (!$file->eof()) {
    $i++;
    $file->next();
}
print "file has " . $i . " lines"; 

Solution 2

iterator_count and line-by-line iterating using next() is broken in my php version 5.3.7 under Ubuntu.

Also seems broken fseek([any offset], SEEK_END) method. key() returns 0.

Iterate over large files using seek($lineCount) is too slow.

Simpliest 5.3.7-verified way is

// force to seek to last line, won't raise error
$file->seek($file->getSize());
$linesTotal = $file->key();

Counting 30000 lines requires now 0.00002 secs and costs about 20 kb of memory.

Iterations method takes about 3 seconds.

Solution 3

I agree with Николай Конев on using seek function is much faster than going through the entire file line by line, but as Twisted1919 said using the file size to seek the last line is confusing so my suggestion is use PHP_INT_MAX instead of the file size:

// force to seek to last line, won't raise error
$file->seek(PHP_INT_MAX);
$linesTotal = $file->key();

Solution 4

The SplFileObject offers an itertor, one iteration per line:

$numberOfLines = iterator_count($file);

The function iterator_count is your friend here, doing the traversal for you and returning the number of iterations.

You can make use of the file object's SKIP_EMPTY flag to not count empty lines in that file.

Share:
11,588
Richard Knop
Author by

Richard Knop

I'm a software engineer mostly working on backend from 2011. I have used various languages but has been mostly been writing Go code since 2014. In addition, I have been involved in lot of infra work and have experience with various public cloud platforms, Kubernetes, Terraform etc. For databases I have used lot of Postgres and MySQL but also Redis and other key value or document databases. Check some of my open source projects: https://github.com/RichardKnop/machinery https://github.com/RichardKnop/go-oauth2-server https://github.com/RichardKnop

Updated on June 28, 2022

Comments

  • Richard Knop
    Richard Knop almost 2 years
    $file = new SplFileObject('/path/to/file.txt');
    

    How can I find the number of lines in a file with SplFileObject?

  • Richard Knop
    Richard Knop over 12 years
    I used fopen/fgets traditional way of reading files as you recommended, thanks. Sometimes I am just trying to do everything with classes when it's not needed.
  • Jan Dragsbaek
    Jan Dragsbaek over 12 years
    If you want to do your filehandling in an object oriented way, thats exactly why SPL exists.
  • Typo
    Typo over 10 years
    Great answer but on larger file (10mb and 135,000+ lines in this case) it is entirely too slow and an attempt to count using this method actually results in a time out.
  • Twisted1919
    Twisted1919 over 10 years
    this is wrong, seek() will look for line number while getSize() will return the filesize in bytes.
  • Николай Конев
    Николай Конев over 10 years
    I know. It just ensures that we seeked all file lines (even if all of them are empty). At most common cases, seek() will bump to EOF on line number that definitely less than bytes count, but PHP handles it silently, returning last line number. Agree, it is dirty hack, but i didn't found any "clean" way to count lines quickly.
  • Bala
    Bala almost 7 years
    works fine. But file has 99 lines but it returns 98. do you know why?
  • Simon
    Simon about 3 years
    NOTE: key returns the index of the last line so this will always be one short of the total. You need to add one to the total: $linesTotal = $file->key() + 1;