如何逐行处理大型 CSV 文件?

Posted

技术标签:

【中文标题】如何逐行处理大型 CSV 文件?【英文标题】:How can I process a large CSV file line by line? 【发布时间】:2018-01-18 16:55:43 【问题描述】:

我已经成功编写了一个脚本,该脚本使用 cURL 下载 CSV 文件,然后将 CSV 解析为数组,如下所示:

$rows = array_map(function($a) 
    return str_getcsv($a, $delimiter);
, explode("\n", $result));

然后我使用foreach 遍历$rows 以将某些内容保存到数据库中。

脚本运行良好,但是当使用较大的 CSV 文件(>10.000 行)时,脚本会变得相当慢,并且会出现更多错误。

我想将 CSV 文件切成小块,因此不会将整个文件导入到变量中。我找到了以下solution,但它仍然一次处理整个文件。

有没有一种方法可以将 CSV 切成小块并多次运行数据库功能?或者有没有更好的方法来处理这样的大型 CSV 文件?

我对处理大文件比较陌生,所以请善待!

【问题讨论】:

也许如果您显示更多代码,我们可能会更有帮助 使用您链接的解决方案逐行读取 csv 并在每 x 行之后将它们全部写入文件,清除内存并开始一个新文件。 【参考方案1】:

将文件保存在某处,然后像这样分块处理它:

<?php
$filePath = 'big.csv';

//How many rows to process in each batch
$limit = 100;

$fileHandle = fopen($filePath, "r");
if ($fileHandle === FALSE)

    die('Error opening '.$filePath);


//Set up a variable to hold our current position in the file
$offset = 0;
while(!feof($fileHandle))

    //Go to where we were when we ended the last batch
    fseek($fileHandle, $offset);

    $i = 0;
    while (($currRow = fgetcsv($fileHandle)) !== FALSE)
    
        $i++;

        //Do something with the current row
        print implode(', ', $currRow)."\n";

        //If we hit our limit or are at the end of the file
        if($i >= $limit)
        
            //Update our current position in the file
            $offset = ftell($fileHandle);

            //Break out of the row processing loop
            break;
        
    


//Close the file
fclose($fileHandle);

【讨论】:

如果限制大于行数,我们可以: $chunkValOpt = [5000,1000, 500, 100, 10, 2, 1]; $块 = 1; foreach ($chunkValOpt as $value) $result = $this->chooseChunkSize( $value, $filePath ) ; if($result != 0) $chunk = $value;休息; //// chooseChunkSize( $value, $filePath ) - 几乎是相同的函数,它返回 $tmp 计数器,其中第二个 while 仅包含:$i++;if($i >= $chunk)$tmp++;跨度>

以上是关于如何逐行处理大型 CSV 文件?的主要内容,如果未能解决你的问题,请参考以下文章

如何快速处理大型csv文件?

在 R 中处理大型 csv 文件

如何打破大型csv文件,在多个核心上处理它并使用nodeJs将结果合并为一个

R中的流处理大型csv文件

在R语言 中如何把list对象逐行写入csv文件中

如何在 React 中逐行读取磁盘中的大 csv 文件?