【问题标题】:PHP loading large csv file - memory issuesPHP加载大型csv文件 - 内存问题
【发布时间】:2016-01-17 21:37:41
【问题描述】:

我有以下代码

$file="postcodes.csv";
$csv= file_get_contents($file);
$array = array_map("str_getcsv", explode("\n", $csv));
$json = json_encode($array);
print_r($json);

postcodes.csv 大小为 603MB,因此文件很大。

在 php.ini 中,如果我有

memory_limit=1024M

我得到了错误

致命错误:允许的内存大小为 1073741824 字节已用尽(已尝试 分配 256 字节)在 ...

如果我将内存限制增加到 2056,我会收到错误

致命错误:内存不足(分配1919680512)(试图分配 36 字节)在...

如果我把它改成-1也是类似的。

那么我怎样才能在没有内存问题的情况下加载这个 csv 文件呢?

谢谢

【问题讨论】:

  • 除非你真的需要一次在内存中的所有行(这很少见),我建议部分处理它们 - 最坏的情况是“读取一行,处理它,输出,重复。”
  • 我同意上述观点,但为了分析这一点:PHP 是否在将每个字符转换为您的本机 CPU 字长时读取它?如果是这样,请尝试将您的 memory_limit 增加到至少 4 * 或 8 * 输入文件中的字符数,具体取决于您的体系结构,并查看是否有帮助。免责声明:我还没有在 PHP 中完成文件读取。
  • 第 2-4 行的基本意思是:将所有约 600 MB 的数据一次保存在内存中至少 3 次(作为字符串、作为数组、作为 JSON 字符串)。这实际上是一个很好的例子,如何不做那样的事情。对不起。 :)

标签: php memory


【解决方案1】:

您可以逐行读取文件。

例如,

$file="postcodes.csv";
$array = array();
if (($handle = fopen($file, "r")) !== FALSE) {
    while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
        $array[]=$data;
    }
    fclose($handle);
}
$json = json_encode($array);
print_r($json);

但是如果你有很多数据并且你的数组太大,内存问题仍然会发生

【讨论】:

    【解决方案2】:

    如果您正在阅读一个大文件,我建议您使用文件指针和fgetcsv() 函数并逐行循环而不是加载整个文件。

    另外,换行不一定意味着 CSV 行的结尾,explode("\n", $csv) 可能会给你一些不想要的结果...使用fgetcsv() 会更安全

    【讨论】:

      【解决方案3】:

      不是将完整文件放入变量中,而是解析它以换行,然后对每个数组元素执行str_getcsv

      根据您所追求的,一个完整的 json 包含每一行的所有值或多个 json 字符串,每个 csv 行一个。

      $h = fopen("postcodes.csv",);
      
      if ($h !== FALSE) {
          $str ='';
          while (($data = fgetcsv($handle)) !== FALSE) {
      
              $str .= json_encode($data); // add each json string to a string variable, save later
              // or
              $array[]=$data;     
          }
      }
      fclose($h);
      
      $finalJsonString = json_encode($array);
      

      我不建议您 print_r 整个 arrayjson 这样大小的对象,因为它很难跟上。

      【讨论】:

        【解决方案4】:

        答案很简单,你需要在 php.ini 中增加 memory_limit,因为文件有 603MB,但是在代码中使用所有这些函数会根据 json 数据在内存中创建一些结构,这超过了 603MB。 Alernativley 您可以优化内存使用更改代码,但您的问题是如何增加内存限制。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-02-18
          • 1970-01-01
          • 2012-03-14
          • 1970-01-01
          • 2011-06-26
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多