从巨大的文本文件中提取单行的PHP方法

3

我对PHP还算熟悉,但可能不如这里的一些人那么好。

我基本上正在尝试找到一种方法来从一个巨大的文本文件中获取一行......它基本上是一个关键字列表,我想按行号调用,但最好不要在到达该行之前遍历它们全部.....否则可能会使我的服务器崩溃。

目前我正在使用以下代码:

$lines = file('http://www.mysite.com/keywords.txt');
foreach ($lines as $line_num => $line) {
   echo "$line_num";
}

这段代码可以运行,但我相信肯定有更好的方式来减少使用量,因为这会将整个文件放入内存中,如果可以直接告诉php给我第97行,会更好。希望你们能提出解决方案,因为你们比我聪明:P ty

1
为什么你不使用数据库来处理这个? - Will Palmer
3个回答

2
使用SplFileObject
 $file = "test.txt";
  $line_number = 1000;
  $file_obj = new SplFileObject( $file );
    /*** seek to the line number ***/
  $file_obj->seek( $line_number );

   /*** return the current line ***/
   echo  $file_obj->current();

1
你需要先下载该文件。 - Carlos Campderrós
1
这段代码的作用是迭代文件中的每一行。在普通文本文件中,没有神奇的方法可以直接跳转到特定的行,必须通过迭代来实现。这一点非常重要。 - EFraim
我刚刚尝试了SplFileObject,它的表现非常出色...谢谢@anup-singh - Vikas
如果必须迭代文件,那么这怎么可能更快呢? - webnoob

2

如果这些行只是文本且长度不等,则无法确定哪一行是第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");

并在毫秒内获取您的数据。

0

在几乎任何语言中,没有办法从文件中获取“第x行”的内容,而不必先以某种方式读取它。毕竟,一行只是两个换行符之间的内容。虽然可以在不加载整个文件的情况下(有些困难)从文件中选择“第x个字符”,但是要选择“第x行”则需要加载所有行直到x(在大多数方法中,您需要加载所有行)

一种加载所有行直到第x行的方法如下(使用fgets):

$f = fopen('http://www.mysite.com/keywords.txt');
$i=97
$text=""
while (($text = fgets($f,2048)) !== false && $i>0) {
       $i--
}
echo $text

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接