PHP fgetcsv()和str_getcsv()没有在Delimiter旁边使用Double Enclosure进行解析

时间:2013-09-04 01:32:03

标签: php csv fgetcsv

我必须使用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手册等等,似乎无法使其正常工作。即使我用反斜杠手动转义内部双引号集,我仍然得到不正确的结果数组。无论我如何使用这两种功能,我的脚本都会陷入困境并尝试将字段拆分为“Avenue”之后的逗号并忽略剩余的“”。

我觉得这个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。

提前感谢您看一下。

1 个答案:

答案 0 :(得分:1)

我能够通过扩展Daniel和Cosades留下的评论来解决问题。我没有使用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++;
}

感谢您指出我正确的方向!