fgetcsv/fputcsv $ escape参数从根本上打破了

qui*_*tin 10 php csv

概观

fgetcsvfputcsv支持一个$escape参数,然而,它要么被破坏,要么我不理解它应该如何工作.忽略这样一个事实,即您没有看到记录的$escape参数fputcsv,它在PHP源代码中受支持,有一个小错误阻止它在文档中出现.

该函数还支持$delimiter$enclosure参数,分别默认为逗号和双引号.我希望$escape传递参数是为了让一个字段包含任何一个元字符(反斜杠,逗号或双引号),但事实并非如此.(我现在从阅读维基百科了解到,这些都用双引号括起来).

我试过的

例如,fgetcsv文档中评论部分中影响众多海报的陷阱.我们想要在字段中写一个反斜杠的情况.

$r = fopen('/tmp/test.csv', 'w');
fwrite($r, '"\"');
fclose($r);

$r = fopen('/tmp/test.csv', 'r');
var_dump(fgetcsv($r));
fclose($r);
Run Code Online (Sandbox Code Playgroud)

这回来了false.我也尝试过"\\",但是也会回来false.用一些含糊不清的文本填充反斜杠会fgetcsv得到它需要的提升...... "hi\\there"并且"hi\there"解析并得到相同的结果,但结果只有1个反斜杠,那么究竟是什么意思$escape呢?

我没有在双引号中包含反斜杠时观察到相同的行为.编写包含字符串的'CSV'文件\,并\\在解析时得到相同的结果fgetcsv,1反斜杠.

让我们问一下PHP如何将反斜杠编码为CSV中的字段 fputcsv

$r = fopen('/tmp/test.csv', 'w');
fputcsv($r, array('\\'));
fclose($r);
echo file_get_contents('/tmp/test.csv');
Run Code Online (Sandbox Code Playgroud)

结果是一个双引号封闭的单反斜杠(我已经尝试了3个版本的PHP> 5.5.4,当$enclose支持被添加到fputcsv)时.这个的欢闹是fgetcsv根据我上面的笔记甚至无法正确阅读它,它会返回false...我希望fputcsv不要用双引号括起反斜杠或者fgetcsv能够"\"按照fputcsv写入来阅读...,或者真的,我显然误解的心,为fputcsv写一个双引号括反斜杠并fgetcsv能够正确地解析吧!

可重复的测试

尝试使用单个引号写入文件fputcsv,然后通过它读取fgetcsv.

$aBackslash = array('\\');

// Write a single backslash to a file using fputcsv
$r = fopen('/tmp/test.csv', 'w');
fputcsv($r, $aBackslash);
fclose($r);

// Read the file using fgetcsv
$r = fopen('/tmp/test.csv', 'r');
$aFgetcsv = fgetcsv($r);
fclose($r);

// Compare the read value from fgetcsv to our original value
if(count(array_diff($aBackslash, $aFgetcsv)))
  echo "PHP CSV support is broken\n";
Run Code Online (Sandbox Code Playgroud)

问题

退后一步我有一些问题

  • 什么是点$escape参数?
  • 鉴于CSV文件的定义松散,可以说PHP 正确支持它们吗?
  • 在CSV文件中对反斜杠进行编码的"正确"方法是什么?

背景

当一位同事为我提供了一个由Python生成的CSV文件时,我最初发现了这一点,该文件写出了一个由双引号括起来的单反斜杠,并且在fgetcsv读取之后失败了.我有高句问他是否可以使用标准的 Python函数.我几乎不知道PHP CSV工具包是一个纠结的混乱!(FWIW:Python开发人员告诉我他正在使用CSV写入模块).

Ja͢*_*͢ck 5

快速浏览Python的CSV格式参数文档,在封闭值(即双引号内)中使用的转义字符是另一个双引号。

对于PHP,默认的转义字符是反斜杠(^);要匹配Python的行为,您需要使用以下代码:

$data = fgetcsv($r, 0, ',', '"', '"');
Run Code Online (Sandbox Code Playgroud)

(^)实际上fgetcsv()处理二者的$enclosure||$enclosure$escape||$enclosure以同样的方式,因此,$escape参数被使用,以避免治疗反斜杠作为特殊字符。

(^^)将$length参数设置为0而不是固定的硬限制会降低效率。