如何在PHP中逐行有效地读取和解析大的CSV文件

如何在PHP中逐行有效地读取和解析大的CSV文件

如何在PHP中逐行有效地读取和解析大的CSV文件

在项目开发中,你可能遇到这样的需求,将一个100G的CSV文件导入到公司的核心数据库中,不是所有的字段,而是进行筛选的字段,100G的csv文件大约有3000万行数据。怎么实现呢,有人说通过phpmyadmin之类的工具导入,但是他们不支持字段修改导入,怎么办呢?

在本文中,我们将向您介绍在PHP中有效读取巨大CSV文件的方法。

一、将文件拆分为较小的块

首先,当我们谈论巨大的文件时,我们并不是在谈论具有50K或70K行的文件,而是像本示例一样,谈论数百万行的CSV文件(25GB)。因此,在这种情况下,正确的方法不是直接使用文件,而是使用较小的文件。

文件越小,不仅在性能方面,而且在逻辑方面,具有最佳性能和对脚本的控制将越好。我们之前写过一篇文章,介绍了如何使用 Windows 10的工具CSV splitter将巨大的CSV数据集拆分为较小的块。您当然可以使用另一种方法来做同样的事情,但是您的想法正确吗?将文件拆分为较小的块,稍后您的脚本可以轻松对其进行处理。

二、实现读取和迭代脚本

要读取文件,我们将使用PHP的fopen函数,该内置函数用于简单地从本地URL打开文件,用于将资源绑定到流。它期望第二个参数是我们将在其中操作的模式,在这种情况下,仅使用r标识符读取即可。只要文件存在,该方法就会返回文件指针,否则在失败的情况下将返回False。

我们将使用此方法读取文件,并将指针存储到$handle变量中。同时创建一个将存储当前行号的变量,因为我们将使用条目控制的循环(while)在行上进行迭代。通过while循环,我们将遍历文件的每一行,以验证fgets始终返回某些内容的条件。

PHP的fgets函数从带有fopen的打开文件中返回一行,并且在没有要读取的内容时返回false。然后,在while循环内,您将可以使用str_getcsv函数解析原始CSV字符串。实施了基本的内容之后,您就可以修改脚本以在PHP中获得最佳性能而做所需的一切:

代码如下:

<?php
// Read a CSV file
$handle = fopen("my_huge_csv_file.csv", "r");

// Optionally, you can keep the number of the line where
// the loop its currently iterating over
$lineNumber = 1;

// Iterate over every line of the file
while (($raw_string = fgets($handle)) !== false) {
// Parse the raw csv string: "1, a, b, c"
$row = str_getcsv($raw_string);

// into an array: ['1', 'a', 'b', 'c']
// And do what you need to do with every line
var_dump($row);

// Increase the current line
$lineNumber++;
}

fclose($handle);
?>


这种方法的优点是:

您不会像读取内存中那样直接读取整个文件file_get_contents,因此运行脚本所需的最大内存量取决于输入数据中的最长行。
很容易阅读和理解。

{{collectdata}}

网友评论0