php从巨大的文本文件中拉出一行

时间:2013-02-18 11:13:55

标签: php

我对PHP很好,但可能不如你们这些人的一半好。

我基本上试图找到一种方法从一个巨大的,我的意思是巨大的文本文件中抓取一条线......它基本上是一个关键字列表,我想通过行号调用,但最好不要在我之前通过它们到达那条线.....否则显然会破坏我的服务器。

目前我正在使用这个

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

这有效,但我确定这是一个更好的方法来节省使用,因为这是把整个文件放入内存,如果我可以简单地说到php给我行号97,那将是规则......

希望你们能提出一个比我更聪明的解决方案:P ty

3 个答案:

答案 0 :(得分: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 :(得分: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);

或多或少是即时的。

如果文件位于远程服务器上,您仍然需要下载整个文件(直到所需的行),并且可以通过在可以运行的远程服务器上放置“扫描程序”脚本来获得更好的服务搜索。然后你可以运行

$text = file_get_contents("http://www.mysite.com/keywords.php?line=97");

以毫秒为单位获取你的行。

答案 2 :(得分: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