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

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

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

对不起,我的英语不好!

除非你知道这条线的偏移量,否则你需要阅读每一行。 你可以通过像fgets()这样的循环来丢弃旧的行(你不想要的fgets() 。 (编辑:而不是fgets() ,我会build议@戈登的解决scheme )

可能一个更好的解决scheme是使用数据库,因为数据库引擎会做存储string的繁重工作,并允许(非常有效地)获得某个“行”(这不会是一条线,而是一条logging一个数字ID,但是它们是相同的东西),而不必在它之前读取logging。

试试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调用只是为了certificate这种方法几乎没有记忆。

文件的内容是否改变? 如果它是静态的或相对静态的,你可以在你想要读取数据的地方build立一个偏移量列表。 例如,如果文件每年更改一次,但每天读取数百次,则可以预先计算所需行的偏移量,并直接跳转到这些偏移量:

  $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 

但这完全可能是过度的。 尝试对操作进行基准testing – 比较一下老式的“读取20行”与预先计算/跳转需要多长时间。

 <?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); } ?> 

只是循环通过他们没有存储,例如

 $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 ++; } 

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

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

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

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