【问题标题】:Batching php's fgetcsv批处理 php 的 fgetcsv
【发布时间】:2011-01-03 17:22:31
【问题描述】:

我有一个我无法控制的相当大的 csv 文件(至少对于网络而言)。它有大约 100k 行,而且只会越来越大。

我正在使用 Drupal 模块提要根据这些数据创建节点,它们的解析器以 50 行为一组进行解析。但是,他们的解析器不能正确处理引号,并且无法解析大约 60% 的 csv 文件。 fgetcsv 可以工作,但据我所知并没有批量处理。

在尝试使用 fgetcsv 读取整个文件时,PHP 最终耗尽了内存。因此,我希望能够将事情分解成更小的块。这可能吗?

【问题讨论】:

    标签: php drupal csv feed batch-processing


    【解决方案1】:

    fgetcsv() 通过从给定文件指针一次读取一行来工作。如果 PHP 内存不足,也许您正试图一次解析整个文件,将其全部放入一个巨大的数组中。解决方案是逐行处理它而不将其存储在一个大数组中。

    要更直接地回答批处理问题,请从文件中读取 n 行,然后使用 ftell() 在文件中找到您结束的位置。记下这一点,然后您可以在将来的某个时间通过在fgetcsv() 之前调用fseek() 来返回它。

    【讨论】:

      【解决方案2】:

      好吧,创建一个函数来解析一堆行:

      function parseLines(array $lines) {
          foreach ($lines as $line) {
              //insert line into new node
          }
      }
      

      然后,将其批量处理:

      $numberOfLinesToBatch = 50;
      $f = fopen($file, 'r');
      if (!$f) die('implement better error checking');
      
      $buffer = array();
      while ($row = fgetcsv($f)) {
          $buffer[] = $row;
          if (count($buffer) >= $numberOfLinesToBatch) {
              parseLines($buffer);
              $buffer = array();
          }
      }
      if (!empty($buffer)) {
          parseLines(buffer);
      }
      
      fclose($f);
      

      它将数据流入,您可以通过调整变量来调整它缓冲的行数...

      【讨论】:

        【解决方案3】:

        我怀疑问题在于您在内存中存储了太多信息,而不是如何从磁盘读取 CSV 文件。 (即:fgetcsv 一次只会读取一行,所以如果一行的数据导致你内存不足,你就有麻烦了。)

        因此,您只需使用以下方法:

        1. 将“x”行读入数组。
        2. 处理此信息
        3. 清除所有临时变量/数组。
        4. 重复直到 FEOF。

        或者,您可以通过 PHP 的命令行版本执行 CSV 处理,并使用具有更大内存限制的自定义 php.ini。

        【讨论】:

          猜你喜欢
          • 2019-01-26
          • 2013-06-07
          • 1970-01-01
          • 2014-07-06
          • 1970-01-01
          • 2019-08-22
          • 2018-11-02
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多