我正在尝试在我的Symfony应用程序中构建一个名为DataFileParser
的服务,该服务读取csv文件。为了这个问题,我更改了我的服务的parse
函数,使其看起来更简单:在我的代码片段中,我的函数只是循环遍历csv文件的行并转储它们。
我的DataFileParser
看起来像这样:
class DataFileParser
{
/**
* @param string $filename
* @param array $expectedColumns
*
* @return EntryIterator
*/
public function parse($filename, $requiredColumns, $expectedColumns)
{
$splFileObject = new \SplFileObject($filename, 'r');
$splFileObject->setFlags(\SplFileObject::READ_CSV);
$splFileObject->setCsvControl(';');
foreach ($splFileObject as $line) {
var_dump($line);
}
die;
}
}
我的csv文件如下所示:
firstname;lastname;mail
john;small;jonh.small@fakemail.com
我的解析函数输出如下所示:
array(5) {
[0]=> string(9) "firstname"
[1]=> string(8) "lastname"
[2]=> string(9) "mail john"
[3]=> string(5) "small"
[4]=> string(23) "jonh.small@fakemail.com"
}
正如您在索引#2上看到的那样,SplFileObject没有检测到最后一个标题" mail"之间的行尾。和#34;约翰"字符串,因为它打印[2]=> string(9) "mail john"
,而我本来期望以下
[2]=> string(4) "mail"
[2]=> string(4) "john"
如果我使用Symfony的var_dumper
组件的转储功能而不是var_dump
,我会得到这个
array:5 [▼
0 => "firstname"
1 => "lastname"
2 => "mail\rjohn"
3 => "small"
4 => "jonh.small@fakemail.com"
]
如您所见,SplFileObject未检测到\r
作为第一行的结尾。
如果我通过在SplFileObject构造函数之前调用'auto_detect_line_endings'
来手动将PHP参数ini_set('auto_detect_line_endings',true);
设置为true,那么它可以正常工作并且我使用转储函数获得以下输出(正确的)。
array:3 [▼
0 => "firstname"
1 => "lastname"
2 => "mail"
]
array:3 [▼
0 => "john"
1 => "small"
2 => "jonh.small@fakemail.com"
]
最后一个细节,我的解析函数的$filename
参数是类Symfony\Component\HttpFoundation\File\UploadedFile
的一个实例。我的操作系统是Mac OS X El Capitan,我使用的是PHP版本7.1.8的MAMP,我正在使用PhpStorm编辑CSV文件(我检查了我的PhpStorm配置的编码风格,并已将\n
设置为行分隔符)。
如何设置SPLFileObject以将\r
检测为换行而不必更改PHP变量auto_detect_line_endings
?以及通过所有操作系统检测所有类型的换行符(\r
,\n
,\n\r
)作为换行符?
(PS:也许这是我的PhpStorm编辑器的问题,因为我无法弄清楚如何使用回车键插入\n
。所以如果有人知道为什么我的PhpStorm不会插入\n
而是\r
即使我已将\n
定义为行分隔符,我也很乐意分享知识。)
PHPStorm换行符配置截图: