fseek() by line, not bytes?

2019-03-24 07:59发布

I have a script that parses large files line by line. When it encounters an error that it can't handle, it stops, notifying us of the last line parsed.

Is this really the best / only way to seek to a specific line in a file? (fseek() is not usable in my case.)

<?php

for ($i = 0; $i < 100000; $i++)
    fgets($fp); // just discard this

I don't have a problem using this, it is fast enough - it just feels a bit dirty. From what I know about the underlying code, I don't imagine there is a better way to do this.

标签: php file fgets
5条回答
相关推荐>>
2楼-- · 2019-03-24 08:38

If you only have the line number to go on, there is no other method of finding the line. Files are not line based (or even character based), so there is no way to simply jump to a specific line in a file.

There might be other ways of reading the lines in the file that might be slightly faster, like reading larger chunks of the file into a buffer and read lines from that, but you could only hope for it to be a few percent faster. Any method to find a specific line in a file still has to read all data up to that line.

查看更多
Summer. ? 凉城
3楼-- · 2019-03-24 08:39
rewind($handle);
while($i=0; $i<$desired_line; i++)
    fgetcsv($handle, 1000, ",")

This is working for me while I need to rewind to a specific line multiple times in my script.

I am not sure if this eats up memory or speed, but it does the trick.

查看更多
对你真心纯属浪费
4楼-- · 2019-03-24 08:49

An easy way to seek to a specific line in a file is to use the SplFileObject class, which supports seeking to a line number (seek()) or byte offset (fseek()).

$file = new SplFileObject('myfile.txt');
$file->seek(9999);     // Seek to line no. 10,000
echo $file->current(); // Print contents of that line

In the background, seek() just does what your PHP code did (except, in C code).

查看更多
Rolldiameter
5楼-- · 2019-03-24 08:51

I know it is late for posting but it can help some ppl I did a function like fseekbyline one day ...

function GoToLine($handle,$line)
{
  fseek($handle,0);  // seek to 0
  $i = 0;
  $bufcarac = 0;                    

  for($i = 1;$i<$line;$i++)
  {
    $ligne = fgets($handle);
    $bufcarac += strlen($ligne);  // in the end bufcarac will contains all caracters until the line
  }  

  fseek($handle,$bufcarac);
}

there is no error system, if you wanna go to the line <1 or 203 but the file is empty ... you will get nothing good.

same if you wanna go out of eot

查看更多
放荡不羁爱自由
6楼-- · 2019-03-24 08:57

If I understand correctly, you want to seek to the specific line at some point after you have found an error. If that is the case, you probably store or print the line-number of the bad line somewhere, depending on what you mean by "notify".

Unless you really mean that you cannot use fseek()*, what you can do is to also store/print the position in the file where the bad line starts. Then you can fseek().

* How, in that case, would fseekbyline() be usable if it existed?

查看更多
登录 后发表回答