45

Using PHP, how can I get the total number of rows that are in a CSV file? I'm using this method but cannot get it to work properly.

if (($fp = fopen("test.csv", "r")) !== FALSE) { 
  while (($record = fgetcsv($fp)) !== FALSE) {
      $row++;
  }

  echo $row;
}
busytraining
  • 723
  • 8
  • 14
telexper
  • 2,381
  • 8
  • 37
  • 66
  • This kind of solution should work, but the problem is the "while(record...) bit, potentially; It breaks on empty lines. Note; none of the offered solutions that count lines in the file are reliable, as they are only counting the lines, not the csv entries (which can contain newline characters) – Steve Horvath Dec 04 '19 at 03:33

10 Answers10

87

Create a new file reference using SplFileObject:

$file = new SplFileObject('test.csv', 'r');

Try to seek to the highest Int PHP can handle:

$file->seek(PHP_INT_MAX);

Then actually it will seek to the highest line it could in the file, there is your last line and the last line + 1 is equals to your total lines:

echo $file->key() + 1;

Tricky, but this will avoid you from loading the file contents into memory, which is a very cool thing to do when dealing with really large files.

Leo Cavalcante
  • 2,327
  • 2
  • 22
  • 30
69

Here's another option using file() to read the entire file into an array, automatically parsing new lines etc:

$fp = file('test.csv');
echo count($fp);

Also, since PHP5, you can pass in the FILE_SKIP_EMPTY_LINES... to skip empty lines, if you want to:

$fp = file('test.csv', FILE_SKIP_EMPTY_LINES);

Manual: http://php.net/manual/en/function.file.php

scrowler
  • 24,273
  • 9
  • 60
  • 92
  • 29
    This works for small file. If you have a huge CSV file (GB size), using file() to read the entire file and count() is probably a bad idea, because it stores the file in memory, and may hang a low memory system. – Tan Hong Tat Jan 30 '14 at 03:59
  • 1
    @TanHongTat is there a more efficient way to do this? – xd6_ Aug 05 '14 at 20:50
  • 4
    @xd6_ [this answer](http://stackoverflow.com/a/21447450/2812842) would be more efficient for large files – scrowler Aug 05 '14 at 20:51
  • 2
    Just be aware that there is no easy way to do all this that would cover 100% of cases simple because the value of CSV column may contain new line character. This means that to get true number of 'records' in the file you would actually have to parse the file. – Alex Skrypnyk Jun 21 '17 at 06:53
15

Try

$c =0;
$fp = fopen("test.csv","r");
if($fp){
    while(!feof($fp)){
          $content = fgets($fp);
      if($content)    $c++;
    }
}
fclose($fp);
echo $c;
Nouphal.M
  • 6,304
  • 1
  • 17
  • 28
7

I know that this is pretty old, but actually I ran into the same question. As a solution I would assume to use linux specific logic:

$rows = shell_exec('$(/bin/which cat) file.csv | $(/bin/which tr) "\r" "\n" | $(which wc) -l');

NOTE: this only works for linux only and this only should be used if you are 100% certain that your file has no multiline-cells

boesing
  • 345
  • 3
  • 10
5

I find this the most reliable:

$file = new SplFileObject('file.csv', 'r');
$file->setFlags(
    SplFileObject::READ_CSV |
    SplFileObject::READ_AHEAD |
    SplFileObject::SKIP_EMPTY |
    SplFileObject::DROP_NEW_LINE
);

$file->seek(PHP_INT_MAX);

$lineCount = $file->key() + 1;
Jonathan
  • 13,947
  • 17
  • 94
  • 123
  • I'd probably upvote this if there was an explanation. I have a policy against upvoting snippet dumps -- even if they are helpful/good. – mickmackusa Dec 17 '20 at 02:26
  • That's a stupid policy. However I won't upvote this because it's already [answered](https://stackoverflow.com/a/43075929/4348570) 3 years prior. – Whip Feb 20 '22 at 04:22
4

CSV rows are separated by line breaks. Therefore, split the rows by line breaks, and you will get an array of rows, which is countable.

if (($fp = fopen("test.csv", "r")) !== FALSE) { 
    $rows = explode("\n", $fp);
    $length = count($rows);

    echo $length;
}
  • 6
    You're not actually reading from the file pointer. And if you're just counting lines, then `count(file("test.csv"))` would achieve it quicker. In some CSV variants however quoted values may enclose linebreaks. – mario Jan 30 '14 at 03:42
4

Note; none of higher-upvoted solutions that count lines in the file are reliable, as they are only counting the lines, not the csv entries (which can contain newline characters)

I'm using a similar solution to op, and it works perfectly, but with op's code the while part can break on empty lines, which is potentially his problem.

So it looks like this (edited op's code)

$rowCount=0;
if (($fp = fopen("test.csv", "r")) !== FALSE) {
  while(!feof($fp)) {
    $data = fgetcsv($fp , 0 , ',' , '"', '"' );
    if(empty($data)) continue; //empty row
    $rowCount++;
  }
  fclose($fp);
}
echo $rowCount;
Steve Horvath
  • 508
  • 1
  • 4
  • 10
  • Isn't this essentially the same as [this answer from two years ago](https://stackoverflow.com/a/44902725/2812842)? – scrowler Dec 04 '19 at 18:09
  • Thanks, @Robbie Averill to be honest, I'm not sure if it would lead to the same result in all circumstances - most notably, empty lines. I've a feeling that the other answer would simply count empty lines, while this one definitely won't. Shame on me for skipping reviewing the negative-rated answers, it's indeed reasonably close. – Steve Horvath Dec 05 '19 at 01:05
0

I know this is an old post, but I've been googling this issue, and found that the only problem with the original code was that you need to define $row outside the while loop, like this:

if (($fp = fopen("test.csv", "r")) !== FALSE) { 
$row = 1;
  while (($record = fgetcsv($fp)) !== FALSE) {
      $row++;
  }

Just in case it helps someone :) echo $row; }

Rosamunda
  • 14,620
  • 10
  • 40
  • 70
-1

In case you are getting the file from a form

$file = $_FILES['csv']['tmp_name'];
                $fp = new SplFileObject($file, 'r');
                $fp->seek(PHP_INT_MAX);
                echo $fp->key() + 1;
                $fp->rewind();

Works like charm!!!!!!!!!!!!!!!!!!

kimoduor
  • 504
  • 6
  • 16
-1
$filename=$_FILES['sel_file']['tmp_name'];
$file=fopen($filename,"r");
$RowCount=0;

while ((fgetcsv($file)) !== FALSE) 
{
    $RowCount++;
}

echo $RowCount;
fclose($file);
Komal12
  • 3,340
  • 4
  • 16
  • 25