3

我对 PHP 很好,但可能没有你们中的一些人那么好。

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

目前我正在使用这个

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

这行得通,但我确定必须有更好的方法来节省使用量,因为这是将整个文件放入内存中,如果我可以简单地对 php 说给我第 97 行,嗯,规则......

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

4

3 回答 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();
于 2013-02-18T11:16:58.463 回答
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# 开始,因此您需要两个fget:一个用于去除虚假的 half 关键字,第二个用于读取行号。当您“关闭”时,读取更大的块并将其分成几行会更快。例如,您查找第 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");

并在几毫秒内获得您的线路。

于 2013-02-18T11:23:35.800 回答
0

没有任何方法可以从几乎任何语言的文件中获取“行号 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
于 2013-02-18T11:24:13.827 回答