如果这些行只是文本且长度不等,则无法确定哪一行是第97行;唯一让它成为第97行的原因是前面有96行。
所以你需要读取整个文件直到那个点(这就是SplFileObject所做的):
$fp = fopen("keywords.txt", "r");
while($line--)
{
if (feof($fp))
// ERROR: line does not exist
$text = fgets($fp, 1024); // 1024 = max length of one line
}
fclose($fp);
但是如果您可以在每行之前存储行号,即文件是
...
95 abbagnale
96 abbatangelo
97 abbatantuono
98 ...
然后你可以实现一种二分查找算法:
- start with s1 = 0 and s2 = file length
- read a keyword and line number at seek position s3 = (s1+s2)/2 (*)
- if line number is less than desired, s1 = s3; else s2 = s3; and repeat previous step.
- if line number is the one desired, strip the number from the text and you get the keyword.
(*) 由于该行很可能不会正好从s #开始,所以您需要
两个 fgets:一个用于去除虚假的关键字一半,第二个用于读取行号。当您“接近”时,将更快地读取一个更大的块并将其拆分成行。例如,您寻找第170135行并读取第170180行:最好的做法是将查找位置倒回一千字节,读入一千字节的数据,然后在其中搜索170135。
或者,如果各行的长度不太不同,存储固定大小的行可能是值得的(这里“#”应实际为空格,在行长度中,您需要计算行终止符,\ n或\ r\n):
abbagnale
abbatangelo
abbatantuono
然后,假设每个关键字都是32字节大小。
$fp = fopen("keywords.txt", "r");
fseek($fp, 97 * 32, SEEK_SET);
$text = trim(fgets($fp, 32));
fclose($fp);
如果文件位于远程服务器上,你仍然需要下载整个文件(直到所需行),最好在远程服务器上放置一个“扫描器”脚本来运行搜索。然后你可以运行
would be more or less instantaneous.
$text = file_get_contents("http://www.mysite.com/keywords.php?line=97")
并在毫秒内获取您的数据。