68

I'm trying to read a specific line from a text file using php. Here's the text file:

foo  
foo2

How would I get the content of the second line using php? This returns the first line:

<?php 
$myFile = "4-24-11.txt";
$fh = fopen($myFile, 'r');
$theData = fgets($fh);
fclose($fh);
echo $theData;
?>

..but I need the second.

Any help would be greatly appreciated

Zoe
  • 27,060
  • 21
  • 118
  • 148
Sang Froid
  • 973
  • 1
  • 7
  • 10

12 Answers12

99
$myFile = "4-24-11.txt";
$lines = file($myFile);//file in to an array
echo $lines[1]; //line 2

file — Reads entire file into an array

Blender
  • 289,723
  • 53
  • 439
  • 496
  • 85
    if the file size is huge, this solution will be slow and occupying a lot memory. – Raptor Aug 30 '12 at 09:02
  • 23
    Reading an entire file into memory just to get the second line? I'd say that is a recipe for disaster in some circumstances (see Raptor's comment). – Tomm Jan 06 '15 at 08:04
  • use alex solution in case of larger files. – Hafenkranich May 20 '16 at 15:42
  • Technically correct but hardly an optimal solution, especially when you get the the point where you're dealing with files that are potentially millions of lines long. – GordonM May 16 '17 at 08:26
46

omg I'm lacking 7 rep to make comments. This is @Raptor's & @Tomm's comment, since this question still shows up way high in google serps.

He's exactly right. For small files file($file); is perfectly fine. For large files it's total overkill b/c php arrays eat memory like crazy.

I just ran a tiny test with a *.csv with a file size of ~67mb (1,000,000 lines):

$t = -microtime(1);
$file = '../data/1000k.csv';
$lines = file($file);
echo $lines[999999]
    ."\n".(memory_get_peak_usage(1)/1024/1024)
    ."\n".($t+microtime(1));
//227.5
//0.22701287269592
//Process finished with exit code 0

And since noone mentioned it yet, I gave the SplFileObject a try, which I actually just recently discovered for myself.

$t = -microtime(1);
$file = '../data/1000k.csv';
$spl = new SplFileObject($file);
$spl->seek(999999);
echo $spl->current()
    ."\n".(memory_get_peak_usage(1)/1024/1024)
    ."\n".($t+microtime(1));
//0.5
//0.11500692367554
//Process finished with exit code 0

This was on my Win7 desktop so it's not representative for production environment, but still ... quite the difference.

nimmneun
  • 1,129
  • 13
  • 16
  • 4
    Just keep in mind that `SplFileObject` locks the file. So when class is no longer needed null it (ex. `$spl = null;`) or you'll be denied to do some other operations over that file - deleting, renaming, accessing outside the class, etc. – Wh1T3h4Ck5 Oct 14 '17 at 16:57
21

If you wanted to do it that way...

$line = 0;

while (($buffer = fgets($fh)) !== FALSE) {
   if ($line == 1) {
       // This is the second line.
       break;
   }   
   $line++;
}

Alternatively, open it with file() and subscript the line with [1].

alex
  • 479,566
  • 201
  • 878
  • 984
20

I would use the SplFileObject class...

$file = new SplFileObject("filename");
if (!$file->eof()) {
     $file->seek($lineNumber);
     $contents = $file->current(); // $contents would hold the data from line x
}
Phil
  • 4,029
  • 9
  • 62
  • 107
8

you can use the following to get all the lines in the file

$handle = @fopen('test.txt', "r");

if ($handle) { 
   while (!feof($handle)) { 
       $lines[] = fgets($handle, 4096); 
   } 
   fclose($handle); 
} 


print_r($lines);

and $lines[1] for your second line

Snake Eyes
  • 16,287
  • 34
  • 113
  • 221
balanv
  • 10,686
  • 27
  • 91
  • 137
6
$myFile = "4-21-11.txt";
$fh = fopen($myFile, 'r');
while(!feof($fh))
{
    $data[] = fgets($fh);  
    //Do whatever you want with the data in here
    //This feeds the file into an array line by line
}
fclose($fh);
Phoenix
  • 4,488
  • 1
  • 21
  • 13
  • 4
    By the way, feeding the entire file into an array, such as with `file()` or `file_get_contents()`, isn't recommended in practice if you might be using any big files. For small files it works great. – Phoenix Apr 25 '11 at 06:32
5

This question is quite old by now, but for anyone dealing with very large files, here is a solution that does not involve reading every preceding line. This was also the only solution that worked in my case for a file with ~160 million lines.

<?php
function rand_line($fileName) {
    do{
        $fileSize=filesize($fileName);
        $fp = fopen($fileName, 'r');
        fseek($fp, rand(0, $fileSize));
        $data = fread($fp, 4096);  // assumes lines are < 4096 characters
        fclose($fp);
        $a = explode("\n",$data);
    }while(count($a)<2);
    return $a[1];
}

echo rand_line("file.txt");  // change file name
?>

It works by opening the file without reading anything, then moving the pointer instantly to a random position, reading up to 4096 characters from that point, then grabbing the first complete line from that data.

cantelope
  • 1,147
  • 7
  • 9
  • What would be your solution for exact match on full line content considering speed? – Artis Zel May 07 '23 at 21:11
  • Depends on whether the data is static or unknown. For static a hash table lookup will be the fastest. For unknown/random data, sequential or parallel sequential via threaded process will be fastest, imo – cantelope May 08 '23 at 22:29
3

If you use PHP on Linux, you may try the following to read text for example between 74th and 159th lines:

$text = shell_exec("sed -n '74,159p' path/to/file.log");

This solution is good if your file is large.

mineroot
  • 1,607
  • 16
  • 23
  • 1
    While this solution works if you know where it is going to be deployed, it is not optimal for situations where you don't know the target system. – Tarulia Jun 13 '18 at 16:51
2

You have to loop the file till end of file.

  while(!feof($file))
  {
     echo fgets($file). "<br />";
  }
  fclose($file);
Rikesh
  • 26,156
  • 14
  • 79
  • 87
1

I like daggett answer but there is another solution you can get try if your file is not big enough.

$file = __FILE__; // Let's take the current file just as an example.

$start_line = __LINE__ -1; // The same with the line what we look for. Take the line number where $line variable is declared as the start.

$lines_to_display = 5; // The number of lines to display. Displays only the $start_line if set to 1. If $lines_to_display argument is omitted displays all lines starting from the $start_line.

echo implode('', array_slice(file($file), $start_line, lines_to_display));
Community
  • 1
  • 1
drugan
  • 789
  • 9
  • 10
0

Use stream_get_line: stream_get_line — Gets line from stream resource up to a given delimiter Source: http://php.net/manual/en/function.stream-get-line.php

Sunit
  • 403
  • 1
  • 5
  • 6
0

You could try looping until the line you want, not the EOF, and resetting the variable to the line each time (not adding to it). In your case, the 2nd line is the EOF. (A for loop is probably more appropriate in my code below).

This way the entire file is not in the memory; the drawback is it takes time to go through the file up to the point you want.

<?php 
$myFile = "4-24-11.txt";
$fh = fopen($myFile, 'r');
$i = 0;
while ($i < 2)
 {
  $theData = fgets($fh);
  $i++
 }
fclose($fh);
echo $theData;
?>