单次调用fgetcsv()会耗尽PHP中的大内存限制

时间:2014-07-18 20:14:04

标签: memory nginx php fgetcsv

我试图从平均大小的CSV(10 MB),标题和第一行读取两行。我将PHP的内存限制设置为64 MB。然而,在第二次调用fgetcsv()时,我收到内存耗尽错误。

我已经删除了脚本的每个不必要的部分进行调试,并逐步跟踪内存使用情况,我仍然无法弄明白。第一次调用后,内存使用率低于1 MB,但在第二次调用时,会发生内存耗尽错误。

以下是代码:

<?php
function trace($msg) {
    echo "<br>" . date("Y-m-d H:i:s") . " - " . memory_get_usage() . " bytes - {$msg}";
}

ini_set('display_errors', 'on');
error_reporting(E_ALL);
ob_implicit_flush(true);

trace("CSV Memory Limit test");

$path = "../data/uploaded/1405712684_base_leitores_july2014.csv";
trace("path = {$path}");

$fp = fopen($path, "r");
trace("file pointer opened");

trace("getting header...");
$header = fgetcsv($fp, 1024);
trace("header fetched");
var_dump($header);
trace("header displayed");

trace("fetching another line");
$l1 = fgetcsv($fp, 1024);
trace("line fetched");
var_dump($header);
trace("line displayed");

这是输出:

2014-07-18 16:06:26 - 249544 bytes - CSV Memory Limit test
2014-07-18 16:06:26 - 249800 bytes - path = ../data/uploaded/1405712684_base_leitores_july2014.csv
2014-07-18 16:06:26 - 250840 bytes - file pointer opened
2014-07-18 16:06:26 - 250840 bytes - getting header...
2014-07-18 16:06:26 - 279280 bytes - header fetched
array (size=111)
  0 => string 'razao social' (length=12)
  1 => string 'Identificaao' (length=13)
  2 => string 'save' (length=4)
  3 => string 'id' (length=2)
  4 => string 'categoria' (length=9)
  5 => string 'nome fantasia' (length=13)
  6 => string 'email' (length=5)
  7 => string 'website' (length=7)
  8 => string 'logradouro' (length=10)
  9 => string 'endereco' (length=8)
  10 => string 'numero' (length=6)
  11 => string 'complemento' (length=11)
  12 => string 'bairro' (length=6)
  13 => string 'cidade' (length=6)
  14 => string 'estado' (length=6)
  15 => string 'cep' (length=3)
  16 => string 'localidade' (length=10)
  17 => string 'ddd' (length=3)
  18 => string 'telefone' (length=8)
  19 => string 'fax' (length=3)
  20 => string 'contato' (length=7)
  21 => string 'cargo' (length=5)
  22 => string 'departamento' (length=12)
  23 => string 'ramo de atividade' (length=17)
  24 => string 'data de nascimento' (length=18)
  25 => string 'especialidade' (length=13)
  26 => string 'linha de atuacao' (length=16)
  27 => string 'data de fundacao' (length=16)
  28 => string 'classificacao de leitor' (length=23)
  29 => string 'observacoes' (length=11)
  30 => string 'is_protocolada' (length=14)
  31 => string 'is_assinante' (length=12)
  32 => string 'qtd_reclamacoes' (length=15)
  33 => string 'error' (length=5)
  34 => string 'errorReport' (length=11)
  35 => string 'saved' (length=5)
  36 => string 'onTrash' (length=7)
  37 => string 'SugestAo de matEria' (length=19)
  38 => string 'Campo2
#redacted#' (length=31)
  39 => string '1' (length=1)
  40 => string '0' (length=1)
  41 => string '141657' (length=6)
  42 => string '2000000041' (length=10)
  43 => string '' (length=0)
  44 => string '' (length=0)
  45 => string '' (length=0)
  46 => string 'RUA' (length=3)
  47 => string '#redacted#' (length=15)
  48 => string '#redacted#' (length=3)
  49 => string '' (length=0)
  50 => string 'JABAQUARA' (length=9)
  51 => string 'PARI' (length=4)
  52 => string 'SP' (length=2)
  53 => string '#redacted#' (length=7)
  54 => string '' (length=0)
  55 => string '11' (length=2)
  56 => string '#redacted#' (length=9)
  57 => string '#redacted#' (length=9)
  58 => string '#redacted#' (length=5)
  59 => string '#redacted#' (length=12)
  60 => string '' (length=0)
  61 => string 'Centros Automotivos, Mec‰nicas e Oficinas - Leves' (length=49)
  62 => string '' (length=0)
  63 => string '' (length=0)
  64 => string '' (length=0)
  65 => string '' (length=0)
  66 => string '' (length=0)
  67 => string 'Centros Automotivos, MecAnicas e Oficinas - Leves ' (length=50)
  68 => string 'N' (length=1)
  69 => string '0' (length=1)
  70 => string '0' (length=1)
  71 => string '0' (length=1)
  72 => string '' (length=0)
  73 => string '1' (length=1)
  74 => string '0' (length=1)
  75 => string '' (length=0)
  76 => string '
#redacted#' (length=16)
  77 => string '2' (length=1)
  78 => string '0' (length=1)
  79 => string '228109' (length=6)
  80 => string '2000000041' (length=10)
  81 => string '0800 AUTOMOTIVE' (length=15)
  82 => string '#redacted#@hotmail.com' (length=32)
  83 => string '' (length=0)
  84 => string 'RUA' (length=3)
  85 => string '#redacted#' (length=7)
  86 => string '322' (length=3)
  87 => string '' (length=0)
  88 => string '' (length=0)
  89 => string 'SAO PAULO' (length=9)
  90 => string 'SP' (length=2)
  91 => string '#redacted#' (length=7)
  92 => string '' (length=0)
  93 => string '11' (length=2)
  94 => string '#redacted#' (length=9)
  95 => string '#redacted#' (length=9)
  96 => string '#redacted#' (length=40)
  97 => string 'PROPRIETARIO' (length=12)
  98 => string '' (length=0)
  99 => string 'Centros Automotivos, Mec‰nicas e Oficinas - Leves' (length=49)
  100 => string '' (length=0)
  101 => string '' (length=0)
  102 => string '' (length=0)
  103 => string '' (length=0)
  104 => string '' (length=0)
  105 => string 'Centros Automotivos, MecAnicas e Oficinas - Leves ' (length=50)
  106 => string '' (length=0)
  107 => string '0' (length=1)
  108 => string '0' (length=1)
  109 => string '0' (length=1)
  110 => string 'Registro criado' (length=15)

2014-07-18 16:06:26 - 287608 bytes - header displayed
2014-07-18 16:06:26 - 287608 bytes - fetching another line
( ! ) Fatal error: Allowed memory size of 67108864 bytes exhausted (tried to allocate 72 bytes) in /home/lqdi/quantum.pranaeditora.com.br/sandbox/test_csv_read.php on line 25
Call Stack
#   Time    Memory  Function    Location
1   0.0011  249048  {main}( )   ../test_csv_read.php:0
2   0.0093  287520  fgetcsv ( ) ../test_csv_read.php:25

我在Ubuntu 14.04 LTS上运行php5-fpm(5.5.9)和nginx(1.4.6)。

1 个答案:

答案 0 :(得分:7)

最后,经过大量的轰动,我发现了问题:行结束。

为什么,Mac的Excel正在导出标题为\r\n的CSV,并在所有其他行导出\n。标题很好,但fgetcsv理解第二行是整个文档。

修复是在fopen之前添加以下内容:

ini_set('auto_detect_line_endings',TRUE);

这将使fgetcsv在解析CSV文件时正确检测行结尾。