我制作了一个 PHP 脚本,用于生成之前由另一个进程生成的 CSV 文件。然后,必须通过另一个进程导入 CSV 文件。
旧 CSV 文件的导入工作正常,但在导入新 CSV 文件时,会出现特殊字符问题。
当我用 Notepad++ 打开旧的 CSV 时,它说编码是 UTF-8,当我用它打开新的 CSV 时,它说它们的编码是“ANSI as UTF-8”。
两者有什么区别?
我怎样才能让 fopen 和 fputcsv 使用“纯”?UTF-8 编码?
谢谢!
我制作了一个 PHP 脚本,用于生成之前由另一个进程生成的 CSV 文件。然后,必须通过另一个进程导入 CSV 文件。
旧 CSV 文件的导入工作正常,但在导入新 CSV 文件时,会出现特殊字符问题。
当我用 Notepad++ 打开旧的 CSV 时,它说编码是 UTF-8,当我用它打开新的 CSV 时,它说它们的编码是“ANSI as UTF-8”。
两者有什么区别?
我怎样才能让 fopen 和 fputcsv 使用“纯”?UTF-8 编码?
谢谢!
文件没有问题。“ANSI as UTF-8”表示没有 BOM,但 Notepad++ 通过分析字节模式明确将编码识别为 UTF-8。我通过创建一个包含俄语、希腊语和波兰语文本的文件并将其保存为没有 BOM 的 UTF-8 来测试这一点。这里是:
# Russian
Следующая
# Greek
Επόμενη
# Polish
Więcej
我在另一个编辑器 (EditPad Pro) 中执行此操作,并使用十六进制模式来确保 BOM 不存在。当我在 NPP 中打开它时,它显示编码为“ANSI as UTF-8”,并且所有字符都正确显示。然后,仍然在十六进制模式下,我删除了第一个俄语字符的第一个字节。当我再次在 NPP 中打开它时,它显示编码为“ANSI”,并将文本的非 ASCII 部分显示为mojibake:
; Russian
¡Ð»ÐµÐ´ÑƒÑŽÑ‰Ð°Ñ
; Greek
Επόμενη
; Polish
Więcej
回到 EditPad,这次我添加了 BOM,但没有修复 Cyrillic 字符。这次 NPP 将编码报告为“UTF-8”,并且除了第一个俄语字符之外的所有内容都正确显示,如下所示。“A1”是 UTF-8 中该字符的第二个字节的十六进制表示。它以反色方案显示以指示错误。
# Russian
A1ледующая
# Greek
Επόμενη
# Polish
Więcej
总结一下:在没有 BOM 的情况下,Notepad++ 会查找不能表示 ASCII 字符的字节,因为它们的值大于 127(或7F
十六进制)。如果找到,但它们都符合UTF-8要求的模式,它会将文件解码为 UTF-8,并将状态栏中的编码报告为“ANSI as UTF-8”。
但是,如果它甚至找到一个不符合 UTF-8 行的字节,它就会将该文件解码为“ANSI”,这意味着底层平台的默认单字节编码。如果您的文件已损坏,这就是您所看到的。
编辑:虽然您的文件在没有它的情况下有效,但您可以通过在文件的开头手动写入三个字节来添加 BOM——"EF BB BF"
但应该有更好的方法。您现在如何生成内容?因为它是UTF-8,在某处至少有一个非 ASCII 字符;否则,NPP 会将其报告为“ANSI”。
另一种考虑的可能性:如果您对使用 CSV 文件的过程有任何影响,也许您可以将其配置为期望 UTF-8 没有 BOM。从技术上讲,任何可以使用BOM 解码 UTF-8 但并非没有BOM 的软件都已损坏。Unicode 联盟实际上不鼓励使用 UTF-8 BOM,而不是任何人都在听。
尝试将您的 PHP 脚本也更改为 UTF-8。有时有必要(尽管它可以被绕过)让脚本在数据的相同字符编码中。
值得注意的是,ANSI 为 UTF-8,即没有 BOM 的 UTF-8,如果您将 PHP 文件格式化为 UTF-8,则很有用。如果您的 PHP 文件将 html 输出到浏览器,则 BOM 包含在 HTML 输出中,w3c 验证器明确警告:
在 UTF-8 文件中找到字节顺序标记。
众所周知,UTF-8 编码文件中的 Unicode 字节顺序标记 (BOM) 会导致某些文本编辑器和旧版浏览器出现问题。在得到更好的支持之前,您可能需要考虑避免使用它。
除此之外,我发现 BOM 混淆了 Firefox 的 Firebug,它现在认为您的所有<head>
内容实际上都在<body>
标签中。