注意。
仍然存在bug 46569,它会在调用SplFileObject::seek()到非零位置后破坏SplFileObject::fgetcsv()的使用,然后返回错误行的内容 - 偏移一个
<?php
$file = new SplFileObject('foo/bar.csv');
$file->seek(1);
print_r($file->fgetcsv()); // 读取第3行而不是第2行
(PHP 5 >= 5.1.0, PHP 7, PHP 8)
SplFileObject::fgetcsv — 从文件中读取一行并将其解析为CSV字段
$separator
= ",", string $enclosure
= "\"", string $escape
= "\\"): array|false从以逗号分隔值(CSV)格式的文件中读取一行,并返回包含读取字段的数组。
注意: 此函数会考虑区域设置。例如,如果
LC_CTYPE
为en_US.UTF-8
,则某些单字节编码的数据可能会被错误地解析。
separator
字段分隔符(仅一个单字节字符)。默认为 ,
或先前调用 SplFileObject::setCsvControl() 设置的值。
enclosure
字段包围符(仅一个单字节字符)。默认为 "
或先前调用 SplFileObject::setCsvControl() 设置的值。
escape
转义字符(最多一个单字节字符)。默认为 \
或先前调用 SplFileObject::setCsvControl() 设置的值。空字符串 (""
) 将禁用专有的转义机制。
注意: 通常,字段中的
enclosure
字符通过重复来转义;但是,可以使用escape
字符作为替代。因此,对于默认参数值""
和\"
具有相同的含义。escape
字符除了允许转义enclosure
字符外,没有特殊含义;它甚至不打算转义自身。
从 PHP 8.4.0 开始,依赖于 escape
的默认值已被弃用。需要显式地按位置提供它,或者使用 命名参数,或者通过调用 SplFileObject::setCsvControl()。
当 escape
设置为除空字符串 (""
) 之外的任何值时,可能会导致不符合 » RFC 4180 的 CSV,或者无法通过PHP CSV函数进行往返转换。escape
的默认值为 "\\"
,因此建议将其显式设置为空字符串。默认值将在PHP的未来版本(不早于PHP 9.0)中更改。
返回一个包含读取字段的索引数组,或在出错时返回 false
。
注意:
CSV 文件中的空行将被返回为包含单个
null
字段的数组,除非使用SplFileObject::SKIP_EMPTY | SplFileObject::DROP_NEW_LINE
,在这种情况下,空行将被跳过。
版本 | 描述 |
---|---|
8.4.0 | 依赖于 escape 的默认值现在已被弃用。 |
7.4.0 | escape 参数现在也接受空字符串以禁用专有的转义机制。 |
示例 #1 SplFileObject::fgetcsv() 示例
<?php
$file = new SplFileObject("data.csv");
while (!$file->eof()) {
var_dump($file->fgetcsv());
}
?>
示例 #2 SplFileObject::READ_CSV
示例
<?php
$file = new SplFileObject("animals.csv");
$file->setFlags(SplFileObject::READ_CSV);
foreach ($file as $row) {
list($animal, $class, $legs) = $row;
printf("A %s is a %s with %d legs\n", $animal, $class, $legs);
}
?>
animals.csv 内容
crocodile,reptile,4 dolphin,mammal,0 duck,bird,2 koala,mammal,4 salmon,fish,0
以上示例将输出类似于以下内容
A crocodile is a reptile with 4 legs A dolphin is a mammal with 0 legs A duck is a bird with 2 legs A koala is a mammal with 4 legs A salmon is a fish with 0 legs
SplFileObject::READ_CSV
注意。
仍然存在bug 46569,它会在调用SplFileObject::seek()到非零位置后破坏SplFileObject::fgetcsv()的使用,然后返回错误行的内容 - 偏移一个
<?php
$file = new SplFileObject('foo/bar.csv');
$file->seek(1);
print_r($file->fgetcsv()); // 读取第3行而不是第2行
请注意,在 PHP 8.1 之前的版本中,这可能会根据给定的 SplFileObject 标志返回 NULL 而不是 FALSE。
变更:https://github.com/php/php-src/commit/188b1d4c7c7b3482584e248522d94e06ba616a1c
测试用例:https://3v4l.org/6dQTT
如果您的 CSV 文件没有包含符,您可能会遇到默认情况下数据中识别为包含符的“ ”问题。空 $enclosure 不允许,但您可以使用与 $delimiter 相同的 $enclosure(默认为 \n)来模拟空包含符。
设置分隔符为 '\t' 后,fgetcsv() 在值为空字符串时会截断该值。
解决方法
<?php
$file = new SplFileObject($path);
$file->setFlags(SplFileObject::DROP_NEW_LINE);
while ($file->valid()) {
$line = $file->fgets();
$line = explode("\t", $line);
print_r($line);
}
?>
请注意,由于在 5.3.8 中引入的错误 55807 和 61032,如果示例 #2 中的 csv 在每一行的末尾都有一个换行符,则 foreach 循环将执行 6 次。
最后一次循环中,$row 将为 bool(false)。即使使用 SplFileObject::SKIP_EMPTY 和 SplFileObject::DROP_NEW_LINE,也是如此。
在修复错误之前,解决方法是将 SplFileObject::READ_AHEAD 也添加到 setFlags() 调用中。