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

本文概述

如果你为一家甚至为同一行业的其他公司提供开发服务的公司工作, 那么你可能已经完成了将客户的庞大”数据库”导入公司首选数据库引擎的”绝妙”任务。例如, 在我们公司中, 我们与MySQL合作, 并且我们的客户提出了一个大约25GB的CSV文件, 具有约750万行。

什么?

显然, 由于项目所需的逻辑, 我们不能仅仅通过PHPMyAdmin之类的工具简单地将文件导入数据库, 因为应该修改CSV中的每一行以适应我们的新数据库设计。

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

1.将文件拆分为较小的块

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

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

2.实现读取和迭代脚本

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

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

PHP的fgets函数从带有fopen的打开文件中返回一行, 并且在没有要读取的内容时返回false。然后, 在while循环内, 你将能够使用str_getcsv函数解析原始CSV字符串。实施了基本的内容之后, 你就可以修改脚本以在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一样直接读取内存中的整个文件, 因此运行脚本所需的最大内存量取决于输入数据中的最长行。
  • 很容易阅读和理解。

编码愉快❤️!

来源:

https://www.srcmini02.com/61341.html

微信公众号
手机浏览(小程序)
0
分享到:
没有账号? 忘记密码?