str_getcsv不在多行CSV中将第一列用双引号引起来

安东

我注意到str_getcsv,即使以这种方式传递字符串数据,似乎也没有将它收到的第一个值括在双引号中。

在下面的示例中,第3行中的第一个值是"Small Box, But Smaller",但是在将其运行通过str_getcsv后变为Small Box, But Smaller(没有双引号)。像这样:

// multi-line csv string
$csvString = <<<'CSV'
"Title","Description",Quantity
"Small Box","For storing magic beans.",2
"Small Box, But Smaller","Not sure why we need this.",0
CSV;

// split string into rows (don't use explode in case multi-line values exist)
$csvRows = str_getcsv($csvString, "\n"); // parse rows
echo '<pre>';
print_r($csvRows);
echo '</pre>';

输出:

Array
(
    [0] => Title,"Description",Quantity
    [1] => Small Box,"For storing magic beans.",2
    [2] => Small Box, But Smaller,"Not sure why we need this.",0
)

导致的问题是,如果现在使用解析每行str_getcsv,则第一个值中的逗号会将其拆分为两行。如果它继续运行,请执行以下操作:

foreach($csvRows as &$csvRow) {
    $csvRow = str_getcsv($csvRow); // parse each row into values and save over original array value
}
unset($csvRow); // clean up

// output
echo '<pre>';
print_r($csvRows);
echo '</pre>';

输出:

Array
(
    [0] => Array
        (
            [0] => Title
            [1] => Description
            [2] => Quantity
        )

    [1] => Array
        (
            [0] => Small Box
            [1] => For storing magic beans.
            [2] => 2
        )

    [2] => Array
        (
            [0] => Small Box
            [1] =>  But Smaller
            [2] => Not sure why we need this.
            [3] => 0
        )

)

问题出在最后一个数组值上,该值是4个键而不是3个键的数组。它以value的逗号分隔"Small Box, But Smaller"

另一方面,仅解析一个行字符串即可:

$csvRowData = '"Small Box, But Smaller","Not sure why we need this.",0';
$csvValues = str_getcsv($csvRowData);

echo '<pre>';
print_r($csvValues);
echo '</pre>';

输出:

Array
(
    [0] => Small Box, But Smaller
    [1] => Not sure why we need this.
    [2] => 0
)

为什么会发生这种情况,如何解决多行CSV数据的问题?当多行CSV数据是字符串并且不是直接从文件中读取时,是否有使用多行CSV数据的最佳实践?另外,我需要处理多行值,例如"foo \n bar"这样,我不能只使用explode()first来代替str_getcsv()

安东

经过很多头痛之后,我想我现在已经明白了问题所在。根据PHP人士的说法,“ str_getcsv()旨在将单个CSV记录解析为字段”(请参阅https://bugs.php.net/bug.php?id=55763)。我发现使用str_getcsv()多个行会导致这些记录不太好的问题:

  • 不保留双引号(正如我上文所述)。
  • 值中的换行符使它认为新行已开始。这可能会带来许多意想不到的后果。

我通过创建一个临时文件并将CSV内容写入其中来解决了该问题。然后,我使用读取了文件fgetcsv(),但没有导致上述2个问题。示例代码:

// multi-line csv string
$csvString = <<<'CSV'
"Title","Description",Quantity
"Small Box","For storing magic beans.",2
"Small Box, But Smaller","This value
contains
multiple
lines.",0
CSV;
// ^ notice the multiple lines in the last row's value

// create a temporary file
$tempFile = tmpfile();
// write the CSV to the file
fwrite($tempFile, $csvString);
// go to first character
fseek($tempFile, 0);

// track CSV rows
$csvRows = array();
// read the CSV temp file line by line
while (($csvColumns = fgetcsv($tempFile)) !== false) {
    $csvRows[] = $csvColumns; // push columns to array (really it would be more memory-efficient to process the data here and not append to an array)
}

// Close and delete the temp file
fclose($tempFile);

// output
echo '<pre>';
print_r($csvRows);
echo '</pre>';

结果是:

Array
(
    [0] => Array
        (
            [0] => Title
            [1] => Description
            [2] => Quantity
        )

    [1] => Array
        (
            [0] => Small Box
            [1] => For storing magic beans.
            [2] => 2
        )

    [2] => Array
        (
            [0] => Small Box, But Smaller
            [1] => This value
contains
multiple
lines.
            [2] => 0
        )

)

我还要补充一点,我在GitHub上找到了一些选项,并且找到了两个针对PHP 5.4+和PHP 5.5+的主要项目。但是,我仍在使用PHP 5.3,并且只看到活动受限的选项。此外,其中一些通过写入文件并读取它们来处理CSV字符串。

我还应该注意,PHP文档对str_getcsv()不符合RFC提出了一些意见http : //php.net/manual/en/function.str-getcsv.phpfgetcsv()至少在这种情况下,后者确实满足了我的需求,似乎同样如此。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

Unix-用双引号引起来的CSV环绕第一列

php的str_getcsv在制表符分隔的列表上中断,没有附件,并且用双引号引起来

在Hibernate中将列名称用双引号引起来

exec用双引号引起来

用双引号引起来

从oracle后台处理到csv时避免在列周围用双引号引起来

当第一个命令行参数用双引号引起来时,错误“ 1”“此时是意外的。

用引号引起来的CSV行

用双引号引起来时忽略逗号

如果仅非空字段用双引号引起来,我如何读取CSV文件?

',(用引号引起来)

不要用双引号引起来

sh如何将变量的值附加到文件中sh用双引号引起来的多行

什么是sed comand来修复此文件,所以每行的最后一个值用双引号引起来

在Python中将引号引起来

请给RegEx帮助-用引号引起来的字符串中包含双引号

用单引号而不是双引号引起来的C ++中的转义序列

Vim用引号引起来

选择用引号引起来的文本

Python ::如何在列表中将值的双引号引起来

从csv中读取后,第一列名称用双引号圈出

在IntelliJ的代码编辑器中,将选定的文本用双引号引起来

ASP.NET Core API发送用双引号引起来的字符串

Python:为什么PostgreSQL表中的列名用双引号引起来?

为什么Microsoft.FSharp.Quotations.Patterns中的模式用双引号引起来?

scrapyd异常期望属性名称用双引号引起来

AWS / JSON / shell脚本:期望属性名称用双引号引起来

Python / Json:期望属性名称用双引号引起来

用双引号引起来的字符串拆分问题