PHP脚本处理40000个CSV文件时内存耗尽错误求助
解决PHP处理大量CSV文件时的内存溢出问题
嘿,这个内存溢出问题其实很好搞定,我来帮你拆解下原因和解决方案:
问题根源
你的代码里有两个核心问题导致内存被耗尽:
$data数组未在循环内重置:你没有在每次处理新文件时清空$data,导致这个数组会不断累积所有处理过的CSV内容。4万个文件下来,数组体积直接撑爆了PHP的内存限制。- 一次性加载整个文件到内存:就算重置了数组,要是遇到大体积的CSV,把所有行都存进数组也会占用大量内存,同样可能触发溢出。
解决方案
方案1:修复现有代码的内存泄漏(适合小体积CSV)
只需要在每次循环开始时重置$data数组,确保每次只处理单个文件的内容:
<?php // Read the file for ($x = 0; $x <= 40000; $x++) { // 每次循环重置数组,避免内存累积 $data = []; $file = fopen('export'.$x.'.csv', 'r'); // Iterate over it to get every line while (($line = fgetcsv($file)) !== FALSE) { // Store every line in an array $data[] = $line; } fclose($file); // Remove the first element from the stored array / first line of file being read array_shift($data); // Open file for writing $file = fopen('export'.$x.'.csv', 'w'); // Write remaining lines to file foreach ($data as $fields) { fputcsv($file, $fields); } fclose($file); echo $x; } ?>
方案2:流式处理(推荐,适配所有大小的CSV)
不需要把整个文件加载到内存,直接边读边写跳过第一行,内存占用极低,完全不会出现溢出问题:
<?php for ($x = 0; $x <= 40000; $x++) { $inputFile = 'export'.$x.'.csv'; $outputFile = 'export'.$x.'.tmp.csv'; // 先写临时文件,避免覆盖原文件出错 // 检查文件是否存在 if (!file_exists($inputFile)) { echo "文件 $inputFile 不存在,跳过\n"; continue; } $inHandle = fopen($inputFile, 'r'); $outHandle = fopen($outputFile, 'w'); if (!$inHandle || !$outHandle) { echo "打开文件 $inputFile 失败,跳过\n"; continue; } // 跳过第一行 fgetcsv($inHandle); // 逐行读取并写入 while (($line = fgetcsv($inHandle)) !== FALSE) { fputcsv($outHandle, $line); } fclose($inHandle); fclose($outHandle); // 替换原文件 rename($outputFile, $inputFile); echo "处理完成:$x\n"; } ?>
额外小贴士
- 别盲目调高内存限制:虽然可以通过
ini_set('memory_limit', '256M')或修改php.ini增加内存,但这只是治标不治本,高效的代码才是长久之计。 - 增加错误处理:处理大量文件时难免遇到文件不存在或无法打开的情况,加判断能让脚本更健壮。
- 用glob遍历文件:如果文件名不是严格的
export0.csv到export40000.csv,可以用glob('export*.csv')获取所有CSV文件,更灵活。
内容的提问来源于stack exchange,提问作者Nick lK
相关产品推荐
相关产品推荐

