处理大文件时最大限度地减少内存使用量

如果我们需要解析一个大文件,例如一个包含数百万行的超过 10 MB 的 CSV 文件,有些人会使用 filefile_get_contents 函数,最后点击 memory_limit 设置

允许的内存大小为 XXXXX 字节耗尽

错误。考虑以下来源(top-1m.csv 正好有 100 万行,大小约为 22 MB)

var_dump(memory_get_usage(true));
$arr = file('top-1m.csv');
var_dump(memory_get_usage(true));

这输出:

int(262144)
int(210501632) 

因为解释器需要保存 $arr 数组中的所有行,所以它消耗了大约 200 MB 的 RAM。请注意,我们甚至没有对数组的内容做任何事情。

现在考虑以下代码:

var_dump(memory_get_usage(true));
$index = 1;
if (($handle = fopen("top-1m.csv", "r")) !== FALSE) {
    while (($row = fgetcsv($handle, 1000, ",")) !== FALSE) {
        file_put_contents('top-1m-reversed.csv',$index . ',' . strrev($row[1]) . PHP_EOL, FILE_APPEND);
        $index++;
    }
    fclose($handle);
}
var_dump(memory_get_usage(true));

哪个输出

int(262144)
int(262144)

所以我们不使用单个额外的内存字节,而是解析整个 CSV 并将其保存到另一个文件中,以反转第二列的值。那是因为 fgetcsv 只读取一行,而 $row 在每个循环中被覆盖。