如何在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,因此运行脚本所需的最大内存量取决于输入数据中的最长行。
很容易阅读和理解。
网友评论0