PHP Conference Japan 2024

SplFileObject::fgetcsv

(PHP 5 >= 5.1.0, PHP 7, PHP 8)

SplFileObject::fgetcsv从文件中读取一行并将其解析为CSV字段

描述

public SplFileObject::fgetcsv(string $separator = ",", string $enclosure = "\"", string $escape = "\\"): array|false

从以逗号分隔值(CSV)格式的文件中读取一行,并返回包含读取字段的数组。

注意: 此函数会考虑区域设置。例如,如果LC_CTYPEen_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,在这种情况下,空行将被跳过。

错误/异常

如果 separatorenclosure 的长度不是一个字节,则抛出 ValueError

如果 escape 的长度不是一个字节或空字符串,则抛出 ValueError

变更日志

版本 描述
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

参见

添加注释

用户贡献的注释 6 条注释

android991 at gmail dot com
5年前
注意。
仍然存在bug 46569,它会在调用SplFileObject::seek()到非零位置后破坏SplFileObject::fgetcsv()的使用,然后返回错误行的内容 - 偏移一个
<?php
$file
= new SplFileObject('foo/bar.csv');
$file->seek(1);
print_r($file->fgetcsv()); // 读取第3行而不是第2行
InvisibleSmiley
3年前
请注意,在 PHP 8.1 之前的版本中,这可能会根据给定的 SplFileObject 标志返回 NULL 而不是 FALSE。

变更:https://github.com/php/php-src/commit/188b1d4c7c7b3482584e248522d94e06ba616a1c

测试用例:https://3v4l.org/6dQTT
Denitz
6 年前
如果您的 CSV 文件没有包含符,您可能会遇到默认情况下数据中识别为包含符的“ ”问题。空 $enclosure 不允许,但您可以使用与 $delimiter 相同的 $enclosure(默认为 \n)来模拟空包含符。
v-fpiris at teknober dot com
13 年前
设置分隔符为 '\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);
}
?>
vaughn dot clayton+php at servicetrade dot com
12 年前
请注意,由于在 5.3.8 中引入的错误 55807 和 61032,如果示例 #2 中的 csv 在每一行的末尾都有一个换行符,则 foreach 循环将执行 6 次。

最后一次循环中,$row 将为 bool(false)。即使使用 SplFileObject::SKIP_EMPTY 和 SplFileObject::DROP_NEW_LINE,也是如此。

在修复错误之前,解决方法是将 SplFileObject::READ_AHEAD 也添加到 setFlags() 调用中。
jbrauer
4 年前
此外,虽然包含字符不能为 NULL,但您可以将其设置为 ASCII NUL 字符 chr(0),其实际效果相同。
To Top