在Php中读取文件时如何节省内存?

时间:2010-04-08 22:13:33

标签: php file memory line

我有一个200kb的文件,我在多个页面中使用的文件,但是在每个页面上我只需要1-2行该文件,所以如果我知道行号,我只能读取这些行所需的内容?

例如,如果我只需要第10行,我不想在内存中加载所有行,只是第10行。

抱歉我的英文不好!

7 个答案:

答案 0 :(得分:19)

尝试SplFileObject

echo memory_get_usage(), PHP_EOL;        // 333200

$file = new SplFileObject('bible.txt');  // 996kb
$file->seek(5000);                       // jump to line 5000 (zero-based)
echo $file->current(), PHP_EOL;          // output current line 

echo memory_get_usage(), PHP_EOL;        // 342984 vs 3319864 when using file()

要输出当前行,您可以使用current()echo $file。我觉得使用这种方法更清楚。您也可以使用fgets(),但这将获得下一行。

当然,你只需要中间三行。我添加了memory_get_usage调用只是为了证明这种方法几乎没有记忆。

答案 1 :(得分:3)

除非你知道线的偏移量,否则你需要读取到那一点的每一行。您可以通过使用fgets()之类的文件循环遍历旧行(您不想要的)。 (编辑:而不是fgets(),我会建议@Gordonsolution

可能更好的解决方案是使用数据库,因为数据库引擎将执行存储字符串的繁重工作并允许(非常有效地)获得某个“线”(它不是一条线但是一个带有数字ID的记录,但它相同,但不必读取它之前的记录。

答案 2 :(得分:2)

文件内容是否有变化?如果它是静态的或相对静态的,您可以构建一个要读取数据的偏移列表。例如,如果文件每年更改一次,但是您每天读取数百次,那么您可以预先计算所需行的偏移量并直接跳转到它们,如下所示:

 $offsets = array();
 while ($line = fread($filehandle)) { .... find line 10 .... }
 $offsets[10] = ftell($filehandle); // store line 10's location
 .... find next line
 $offsets[20] = ftell($filehandle);

等等。之后,您可以像这样轻松跳转到该行的位置:

 $fh = fopen('file.txt', 'rb');
 fseek($fh, $offsets[20]); // jump to line 20

但这可能完全是矫枉过正的。尝试对操作进行基准测试 - 比较执行旧式“读取20行”与预计算/跳转所需的时间。

答案 3 :(得分:1)

<?php
    $lines = array(1, 2, 10);

    $handle = @fopen("/tmp/inputfile.txt", "r");
    if ($handle) {
        $i = 0;
        while (!feof($handle)) { 
            $line = stream_get_line($handle, 1000000, "\n");

            if (in_array($i, $lines)) {
                echo $line;
                            $line = ''; // Don't forget to clean the buffer!
            }

            if ($i > end($lines)) {
                break;
            }

            $i++;
        } 
        fclose($handle);
    }
?>

答案 4 :(得分:0)

只需循环浏览它们,例如。

$i = 1;
$file = fopen('file.txt', 'r');
while (!feof($file)) {
   $line = fgets($file); // this gets whole line from the file;
   if ($i == 10) {
       break; // break on tenth line
   } 
   $i ++;
}

上面的例子只保留了从文件中获取的最后一行的内存,所以这是最有效的内存方式。

答案 5 :(得分:0)

使用fgets()。 10次​​:-)在这种情况下,你不会将所有10行存储在内存中

答案 6 :(得分:0)

为什么你只想加载前十行?你知道加载所有这些行实际上是一个问题吗?

如果你没有测量过,那么你不知道这是一个问题。不要浪费时间优化非问题。有可能在没有加载整个200K文件时你所拥有的任何性能变化都是不可察觉的,除非你知道加载该文件确实是一个瓶颈。