【发布时间】:2010-04-08 22:13:32
【问题描述】:
我有一个 200kb 的文件,我在多个页面中使用该文件,但在每个页面上我只需要该文件的 1-2 行,所以如果我知道行号,我如何才能只读取我需要的这些行?
例如,如果我只需要第 10 行,我不想在内存中加载所有行,只需要第 10 行。
对不起,我的英语不好!
【问题讨论】:
我有一个 200kb 的文件,我在多个页面中使用该文件,但在每个页面上我只需要该文件的 1-2 行,所以如果我知道行号,我如何才能只读取我需要的这些行?
例如,如果我只需要第 10 行,我不想在内存中加载所有行,只需要第 10 行。
对不起,我的英语不好!
【问题讨论】:
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 调用只是为了证明这种方法几乎不会占用内存。
【讨论】:
seek 是基于行而不是基于字节的。
fgets 更清楚正在发生的事情(寻找特定行)。
SplFileInfo::fseek() 和SplFileInfo::seek()。后者是基于行的,另一个是基于字节的。 seek() 是来自SeekableIterator 接口的方法。
seek-ed 到的行号不是第 5,000 行。 $line_pos 参数从零开始,因此该示例寻求第 5,001 行,就像在文本编辑器等中看到的那样。
【讨论】:
文件的内容会改变吗?如果它是静态的或相对静态的,您可以在要读取数据的位置构建一个偏移列表。例如,如果文件每年更改一次,但您每天阅读它数百次,那么您可以预先计算您想要的行的偏移量并直接跳转到它们,如下所示:
$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 行”与预计算/跳转需要多长时间。
【讨论】:
<?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 文件时所发生的任何性能变化都可能是难以察觉的。
【讨论】: