【问题标题】:PHP fgetcsv() and str_getcsv() Not Parsing With Double Enclosure Next to DelimiterPHP fgetcsv() 和 str_getcsv() 不解析与分隔符旁边的双包围
【发布时间】:2013-09-04 01:32:02
【问题描述】:

我必须用 PHP 解析一个 CSV 文件。 CSV 文件由客户提供,我无法控制格式。它以逗号分隔并使用双引号作为文本限定符。但是,如果某个字段(例如地址字段)中包含逗号,则客户端的系统会将该字段括在一组额外的双引号中。例如:

"9999X111","X1110000110105","John Doe",""123 Central Park Avenue, #108"","New York NY 10006 ","","","M","0","1","370.20"

如您所见,第 4 个字段(第 3 个索引)在整个字段周围有一组额外的双引号。如果我通过 fgetcsv() 或 str_getcsv() 发送此字符串,则该字段未正确处理。

Unwanted Result Array:
[0] => 9999X111
[1] => X1110000110105
[2] => John Doe
[3] => 555 Central Park Avenue
[4] =>  #108""
[5] => New York NY 10006

如果我手动删除多余的双引号集,则使用任一函数都可以正确处理该行;但是,我无法在生产环境中执行此操作。

Preferred Result Array:
[0] => 9999X111
[1] => X1110000110105
[2] => John Doe
[3] => 555 Central Park Avenue, #108
[4] => New York NY 10006

这是我正在使用的当前代码:

$fileCHG = fopen($fileloc['InputFile'], "r");
$cnt = 0;
while(!feof($fileCHG)) {
    $chg[$cnt] = fgetcsv($fileCHG,0,",","\"");
    if($chg[$cnt]=="") { //Unset Any Blank Arrays
        unset($chg[$cnt]);
    }
    $cnt++;
}

我尝试了来自 Stack Overflow、PHP 手册等的各种建议,但似乎无法使其正常工作。即使我用反斜杠手动转义内部双引号集,我仍然得到不正确的结果数组。无论我如何使用任一函数,我的脚本都会搞砸并尝试在“大道”后面的逗号处拆分字段并忽略剩余的“”。

我觉得 PHP 网站上的这条评论可能正在解释正在发生的事情,但作为一个新编码员,我无法想象实际发生了什么。

http://www.php.net/manual/en/function.fgetcsv.php#58124

我也尝试了以下建议(在众多建议中),但均无济于事。

fgetcsv is not splition data properly str_getcsv not parsing the data correctly

这个方法本来可以的;但它要求每行的字段数相同。

Reading CSV file with unescaped enclosures

我在 Mac OS X 10.8 上使用 PHP 5.3.27。

提前感谢您的观看。

【问题讨论】:

  • 你能假设两组双引号只存在于那种情况下吗?只执行$buf = str_replace('""', '"', $buf); 是否可行?
  • 不幸的是,我不这么认为,因为每个字段都用双引号括起来。因此,如果一个字段是空的,它只会是“”,也许将它处理到某个地方的临时文件?有关如何正确检测这些情况的任何帮助都会很棒。
  • 你能做到吗str_replace('"\",','""',(str_replace('""', '"\"', $buf));' to achieve this? 意图是转义双引号,引号出现在一个附件中,然后更正一个空字段的转义

标签: php csv fgetcsv


【解决方案1】:

我能够通过扩展 Daniel 和 Cosades 留下的 cmets 来解决问题。我没有使用 fgetcsv() 立即处理该行,而是使用 fgets() 将该行存储在一个变量 ($line) 中。然后,我使用 stripos() 来查找重复双引号 ("") 的每次出现的位置。然后,通过确定之前或之后的字符是否不是逗号 (,) 来识别需要编辑的位置。下面是我的新代码。

$fileCHG = fopen($fileloc['Charge'], "r");
$cnt = 0;

while(($line=fgets($fileCHG))!==false){
    $pos = 0;
    while($pos=stripos($line,"\"\"",$pos)){
        $chrA = substr($line,$pos-1,1);
        $chrB = substr($line,$pos+2,1);

        if($chrA!=","){
            $line   = substr_replace($line,"",$pos+1,1);
        }

        if($chrB!=","){
            $line   = substr_replace($line,"",$pos+1,1);
        }   

        $pos = $pos + strlen(",\"\"");
    }

    if($line!=""){
        $chg[$cnt] = str_getcsv($line,",","\"");
    }

    if($chg[$cnt]==""){
        unset($chg[$cnt]);
    }    

    $cnt++;
}

感谢您为我指明正确的方向!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-29
    • 2013-09-08
    • 2023-04-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多