我有一个脚本可以解析 CSV 文件并开始验证电子邮件。这对于 1000 行来说效果很好。但在 1500 万行时,它显示内存耗尽错误。文件大小为 400MB。有什么建议么?如何解析和验证它们?
服务器规格:Core i7 和 32GB RAM
function parse_csv($file_name, $delimeter=',') {
$header = false;
$row_count = 0;
$data = [];
// clear any previous results
reset_parse_csv();
// parse
$file = fopen($file_name, 'r');
while (!feof($file)) {
$row = fgetcsv($file, 0, $delimeter);
if ($row == [NULL] || $row === FALSE) { continue; }
if (!$header) {
$header = $row;
} else {
$data[] = array_combine($header, $row);
$row_count++;
}
}
fclose($file);
return ['data' => $data, 'row_count' => $row_count];
}
function reset_parse_csv() {
$header = false;
$row_count = 0;
$data = [];
}
Run Code Online (Sandbox Code Playgroud)
fel*_*ins 13
将大型数据集(文件行等)推入数组会增加内存使用量,这与处理的项目数量成正比。因此,在这种情况下,文件越大,内存使用量就越大。
因此,与其将数据收集到数组中,不如就地处理它:
$file = fopen($file_name, 'r');
while (!feof($file)) {
$row = fgetcsv($file, 0, $delimeter);
if ($row == [NULL] || $row === FALSE) { continue; }
if (!$header) {
$header = $row;
} else {
// do whatever's intended to do with row
// instead of $data[] = array_combine($header, $row);
do_something($row);
}
}
Run Code Online (Sandbox Code Playgroud)
这里的主要区别是:
您不会立即(从内存中)获取并使用所有数据。您可以按需获取项目(如流)并对其进行处理,一次处理一个项目。它对内存使用有巨大影响。
但是,如果实际工作负载无法轻松移动到循环内部(例如,它是一个需要处理数组的函数),您可以将处理移动到其他地方,同时保持较低的内存占用量。为此,您可以使用生成器。
阅读 PHP 文档,它非常适合您的情况(强调我的情况):
生成器允许您编写使用 foreach 迭代一组数据的代码,而无需在内存中构建数组,这可能会导致您超出内存限制,或者需要大量的处理时间来生成。
像这样的东西:
$file = fopen($file_name, 'r');
while (!feof($file)) {
$row = fgetcsv($file, 0, $delimeter);
if ($row == [NULL] || $row === FALSE) { continue; }
if (!$header) {
$header = $row;
} else {
// do whatever's intended to do with row
// instead of $data[] = array_combine($header, $row);
do_something($row);
}
}
Run Code Online (Sandbox Code Playgroud)
进而:
$generator = csv_read('rdu-weather-history.csv', ';');
do_stuff_with_array($generator);
Run Code Online (Sandbox Code Playgroud)
这里,$generator变量并不同时保存所有数据。一方面,它的行为很像数组,并且可以在foreach()语句内部使用。另一方面,它的行为就像一个流,一次读取一个项目。
PS:上面的 CSV 文件取自: https: //data.townofcary.org/api/v2/catalog/datasets/rdu-weather-history/exports/csv