Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/261.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
PHP-exec awk或fread可以更快地读取非常大文件上的列_Php - Fatal编程技术网

PHP-exec awk或fread可以更快地读取非常大文件上的列

PHP-exec awk或fread可以更快地读取非常大文件上的列,php,Php,我有一个包含绘图数据的文件。每行共有4个坐标,数据文件可以超过1 GB。比如说,我想得到一个数据文件中的第三列,哪种方法应该考虑好的实践和更快的速度? 使用执行: exec("awk '{ print $3 }' data", $output); 使用PHP脚本: $data = file("data"); $points = array(); foreach($data as $line) $points[] = $line[2]; 此外,由于服务器不允许读取大文件,我不得不使用f

我有一个包含绘图数据的文件。每行共有4个坐标,数据文件可以超过1 GB。比如说,我想得到一个数据文件中的第三列,哪种方法应该考虑好的实践和更快的速度? 使用执行:

exec("awk '{ print $3 }' data", $output);
使用PHP脚本:

$data = file("data");
$points = array();
foreach($data as $line)
    $points[] = $line[2];

此外,由于服务器不允许读取大文件,我不得不使用fread来读取文件的几个部分。但fread不够聪明,必须做一些工作来组合每个部分的最后一行。有什么建议或更好的方法可以用php阅读文件中的专栏吗?

fgets是你的朋友-。您可以逐行读取文件,而无需将整个文件加载到内存中。

这里的
/file
是一个3.1 GB的大文件:

root# time awk '{ print $3 }' /file >/dev/null

real   1m42.430s
user   1m0.241s
sys    0m2.198s
好的。awk为±1.7分钟。让我们测试PHP(没有字段分割,只有第三个字符):

PHP±4.3分钟!我不想想象如果我使用@Jack的代码需要多长时间


PHP比awk慢得多。在非常大的文件上,使用awk(由exec()调用)。正如您在这里看到的,PHP在用户空间中花费了大量时间(是awk的三倍)。

您可以在前后添加微时间(true)以获得成本时间。您可以看到哪个更快。fseek可能(不知道,因为系统调用也有一定的成本)这是什么类型的数据文件?是CSV吗?另外,
awk
如何比
fread()
更智能?每个值由1或2个空格分隔。对于一行,将有8个值。在读取一列值时,使用awk将非常方便。似乎使用awk会使用更少的资源,因为使用awk,我可以读取(~5000000行),但使用php foreach,我只能在内存限制为128MB时读取(~700000行)。是的,我检查php使用的资源更多。然而,我一直担心php exec不是一个好的实践,或者有人可能会说它是一个邪恶的实践。我应该一直使用exec还是只是模仿行为?这取决于。如果您想在不受您控制的服务器上分发软件(例如,这些功能可能被禁用的地方等),您应该在PHP中模拟它。(或者最好:检查awk是否存在,是否可以使用exec(),如果没有,则在PHP中模拟它)。但如果可以,选择最快的。eval()、exec()等东西只有在向其传递无效的用户输入时才是有害的。
root# time php -r '$fp = fopen("/file", "r"); while (($buf = fgets($fp)) !== false) echo $buf[2]; fclose($fp);' >/dev/null

real   4m17.322s
user   3m16.571s
sys    0m31.625s