什么是“ANSI as UTF-8”,如何让 fputcsv() 生成带 BOM 的 UTF-8?

2022-08-30 20:42:16

我制作了一个PHP脚本,该脚本生成以前由另一个进程生成的CSV文件。然后,CSV文件必须通过另一个过程导入。

导入旧的 CSV 文件工作正常,但在导入新的 CSV 文件时,存在特殊字符的问题。

当我用记事本++打开旧的CSV时,它说编码是UTF-8,当我用它打开新的CSV时,它说它们的编码是“ANSI作为UTF-8”。

两者之间有什么区别?

我怎样才能让 fopen 和 fputcsv 使用“纯”呢?UTF-8 编码?

谢谢!


答案 1

该文件没有任何问题。“ANSI为UTF-8”意味着没有BOM,但Notepad ++通过分析字节模式明确地将编码标识为UTF-8。我通过创建一个包含俄语,希腊语和波兰语文本的文件并将其保存为没有BOM的UTF-8来测试这一点。在这里:

# Russian
Следующая

# Greek
Επόμενη

# Polish
Więcej

我在不同的编辑器(EditPad Pro)中执行此操作,并使用十六进制模式来确保BOM不存在。当我在NPP中打开它时,它显示编码为“ANSI作为UTF-8”,并且所有字符都正确显示。然后,仍然处于十六进制模式,我删除了第一个俄语字符的第一个字节。当我再次在NPP中打开它时,它将编码显示为“ANSI”,并将文本的非ASCII部分显示为mojibake

; Russian
¡Ð»ÐµÐ´ÑƒÑŽÑ‰Ð°Ñ

; Greek
Επόμενη

; Polish
Więcej

回到EditPad,这次我添加了一个BOM,但没有修复西里尔字符。这次 NPP 将编码报告为“UTF-8”,并且除第一个俄语字符外,所有内容都正确显示,如下所示。“A1”是 UTF-8 中该字符的第二个字节的十六进制表示形式。它以倒置的配色方案显示,以指示错误。

# Russian
A1ледующая

# Greek
Επόμενη

# Polish
Więcej

总而言之:在没有 BOM 的情况下,Notepad++ 会查找无法表示 ASCII 字符的字节,因为它们的值大于 127(或十六进制)。如果找到任何编码,但它们都符合 UTF-8 所需的模式,它会将文件解码为 UTF-8,并将状态栏中的编码报告为“ANSI 为 UTF-8”。7F

但是,如果它找到一个字节,即使它没有达到UTF-8行,它就会将文件解码为“ANSI”,这意味着底层平台的默认单字节编码。如果您的文件已损坏,那就是您将看到的内容。

编辑:虽然你的文件在没有它的情况下是有效的,但你可以通过在文件开头手动写入三个字节来添加BOM - 但应该有更好的方法。您现在如何生成内容?因为它是UTF-8,在某个地方至少有一个非ASCII字符;否则,NPP将将其报告为“ANSI”。"EF BB BF"

另一种需要考虑的可能性是:如果您对使用CSV文件的流程有任何影响,也许您可以将其配置为没有BOM的UTF-8。从技术上讲,任何可以使用BOM解码UTF-8但没有BOM的软件都会被破坏。Unicode Consortium实际上不鼓励使用UTF-8 BOM,而不是任何人在听。


答案 2

根据这里这里的Notepad ++相关线程,“ANSI作为UTF-8”表示没有BOMUTF-8,而普通的“UTF-8”表示带有BOM的UTF-8。因此,读取 CSV 的过程可能需要字节顺序标记才能将 CSV 正确读取为 UTF-8。

但在开始之前,请确保您的脚本确实写入了 UTF-8!当您在记事本++中打开新的 CSV 时(它显示“ANSI 作为 UTF-8”),是否所有“特殊”字符都正确显示?如果没有,您需要调整脚本以实际编写 UTF-8,如果是,请检查 BOM 差异。


推荐