fgetcsv和fputcsv支持$escape
论证,但是,它已被破坏,或者我不理解它应该如何工作。忽略这样一个事实:您没有看到$escape
上记录的fputcsv
参数,它在PHP源代码中受支持,这是一个小错误,阻止它在文档中出现。
该函数还支持$delimiter
和$enclosure
参数,分别默认为逗号和双引号。我希望传递$escape
参数是为了让一个字段包含任何一个元字符(反斜杠,逗号或双引号),但事实并非如此。 (我现在从阅读Wikipedia了解到,这些都用双引号括起来。)
例如,fgetcsv
文档中评论部分中影响众多海报的陷阱。我们想在字段中写一个反斜杠的情况。
$r = fopen('/tmp/test.csv', 'w');
fwrite($r, '"\"');
fclose($r);
$r = fopen('/tmp/test.csv', 'r');
var_dump(fgetcsv($r));
fclose($r);
返回false
。我还尝试了"\\"
,但也会返回false
。用一些含糊不清的文本填充反斜杠会使fgetcsv
得到所需的提升... "hi\\there"
和"hi\there"
都解析并得到相同的结果,但结果只有1个反斜杠,那么$escape
究竟是什么意思呢?
我没有用双引号括起反斜杠时观察到相同的行为。写一个' CSV'包含字符串\
和\\
的文件在由fgetcsv
, 1 反斜杠进行解析时具有相同的结果。
让我们问PHP如何使用fputcsv
$r = fopen('/tmp/test.csv', 'w');
fputcsv($r, array('\\'));
fclose($r);
echo file_get_contents('/tmp/test.csv');
结果是双引号封闭的单个反斜杠(我已经尝试了3个版本的PHP> 5.5.4,当$enclose
支持被添加到fputcsv
时)。这样的欢闹是fgetcsv
根据我上面的笔记甚至无法正确阅读它,它会返回false
...我希望fputcsv
不要将fgetcsv
括起来双引号中的反斜杠或"\"
能够以fputcsv
读取fputcsv
已将其写入...,或真正在我明显误解的心灵中,{ {1}}写一个带有反斜杠对的双引号,并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";
退一步我有一些问题
$escape
参数的重点是什么?当一位同事为我提供了一个由Python生成的CSV文件时,我最初发现了这一点,该文件写出了一个用双引号括起来的单反斜杠,并且fgetcsv
无法读取它。我高兴地问他是否可以使用标准的 Python函数。我几乎不知道PHP CSV工具包是一个纠结的混乱! (FWIW:Python开发人员告诉我他正在使用CSV写入模块)。
答案 0 :(得分:4)
通过快速浏览一下CSV Format Parameters上的Python文档,封闭值(即双引号内)中使用的转义字符是另一个双引号。
对于PHP,默认转义字符是反斜杠(^);要匹配Python的行为,你需要使用它:
$data = fgetcsv($r, 0, ',', '"', '"');
(^)实际上fgetcsv()
以同样的方式处理$enclosure||$enclosure
和$escape||$enclosure
,因此$escape
参数用于避免将反斜杠视为特殊性格。
(^^)将$length
参数设置为0
而不是固定的硬限制会降低效率。
答案 1 :(得分:3)
因此,在睡眠之后重新查看代码,结果是fputcsv不接受escape参数,而我是愚蠢的。我已将下面的代码更新为正确的工作代码。适用相同的基本原则,escape参数用于更改escape参数,因此您可以加载带反斜杠的CSV,而不将它们视为转义字符。诀窍是使用不包含在csv中的字符。您可以通过为特定字符抓取文件来执行此操作,直到找到未返回的文件。
好的,所以判断是它检查转义字符,然后永远不会停止检查。所以,如果它找到它,它就会被逃脱。那很简单。
也就是说,escape参数的目的是允许这种情况,你可以将转义字符改为不需要的字符。
我已将您的示例代码转换为正常工作代码:
$aBackslash = array('\\');
// Write a single backslash to a file using fputcsv
$r = fopen('/tmp/test.csv', 'w');
fputcsv($r, $aBackslash, ',', '"'); // EDIT 2: Removed escape param that causes PHP Notice.
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";
else
echo "PHP WORKS!\n";
一个重要的警告是,fgetcsv
和fputcsv
必须具有相同的参数,否则返回的数组将与原始数组不匹配。
你是对的。这是一种失败的语言。我已经尝试过我能想到的所有斜线,我还没有真正实现CSV的成功响应。它总是像你的例子那样返回。
我认为@deceze所提到的是,在你的例子中,你使用array('\\')
实际上是字符串文字" \"哪个PHP解释为这样,并传递" \"到CSV,然后以这种方式返回。这会返回错误的回复\"
,如上所述,这肯定是错误的。
我确实找到了一个解决方案,所以结果实际上是合适的:
首先,对于您的示例,我们需要使用" \"生成/tmp/test.csv。作为身体,或稍微改变阵列。最简单的方法就是将数组更改为:
array('"\\\\"');
之后,我们应该稍微更改fgetcsv请求。
$aFgetcsv = fgetcsv($r);
$aFgetcsv = array_map('stripslashes', $aFgetcsv);
通过这样做,我们告诉PHP剥离第一个斜杠,从而使字符串在$ aFgetcsv" \"