无法支持使用 ColdFusion 生成的 XML 文件中的非 UTF-8 字符
Unable to support non-UTF-8 characters in XML file generated with ColdFusion
当我 运行 服务器上的以下代码 运行ning ColdFusion 2018:
<cfsetting enablecfoutputonly="yes">
<cfxml variable="test">
<cfoutput>
<test>
áéíóú
</test>
</cfoutput>
</cfxml>
<cfset testString = ToString(test)>
<cfset testStringISO = Replace(testString, "UTF-8", "iso-8859-1")>
<cffile action="write" file="#AbsoluteFilesPath#test.xml" output="#testStringISO#" charset="iso-8859-1">
其中 AbsoluteFilesPath
是对服务器上某个位置的绝对引用。找到了我用来更改 XML 编码的方法 here。当我在服务器上用 Notepad++ 打开 test.xml
文件时,它看起来像这样:
<?xml version="1.0" encoding="iso-8859-1"?>
<test>
αινσϊ
</test>
文件的编码显示为“ISO 8859-7”。
有趣的是,在我的本地机器上用 VSCode 打开文件显示如下:
<?xml version="1.0" encoding="iso-8859-1"?>
<test>
�����
</test>
这里,文件的编码显示为“UTF-8”。在编辑器中选择命令“使用编码 ISO 8859-1 重新打开”显示文件应该是这样的:
<?xml version="1.0" encoding="iso-8859-1"?>
<test>
áéíóú
</test>
我测试了这段代码,将“iso-8859-1”替换为“utf-16”,结果是一样的。
为什么文件编码不一致,不是我想要的?如何确保使用正确的编码创建文件?
让我们先澄清一点:XML 文件中的 encoding
属性只是 reader 的一个指标。它不影响写入实际文件的字节。
所以让我们将示例代码简化为单个字符 á
:
UTF-8 存储 2 个字节,ISO-8859-1 存储 1 个字节。这就是我们所期望的。
示例代码
<cfsetting enablecfoutputonly="true">
<cfxml variable="test">
<cfoutput><r>á</r></cfoutput>
</cfxml>
<cfset xmlForUTF = toString(test)>
<cfset xmlForISO = replace(xmlForUTF, 'encoding="UTF-8"', 'encoding="ISO-8859-1"')>
<cfset fileWrite(expandPath("UTF-8.xml"), xmlForUTF, "UTF-8")>
<cfset fileWrite(expandPath("ISO-8859-1.xml"), xmlForISO, "ISO-8859-1")>
生成的文件
UTF-8.xml
ISO-8859-1.xml
这正是我们所期望的。 cfxml
和 cffile
/fileWrite
都不是问题。 那么为什么在您的机器上使用上述代码可能得不到相同的结果?
问题:页面编码
ColdFusion在解析模板文件(.cfm
)和组件文件(.cfc
)时,会使用JVM的默认编码,如无特别说明,即为系统默认编码。这也是为什么每个人用上面的代码得到不同结果的原因。
如果文件中有诸如 á
之类的文字,则此字符将使用您告诉文本编辑器使用的任何内容进行编码。我们假设是 UTF-8
。如果您检查该文件,您将看到该字符已正确存储。然而,当 ColdFusion 打开这个文件并解析文字时,它会假定该字符使用系统的默认编码进行编码。不幸的是,您似乎 运行 一个不使用或不能使用 UTF-8 作为系统范围代码集的系统(例如 Windows)。
解决方案
一种(丑陋的)解决方法
解决它的(hacky)方法
将 ColdFusion 使用其解析器处理的每个文件(所有 .cfm
/.cfc
文件)保存为 UTF-8 和 BOM。当 ColdFusion 在文件开头遇到这些字节时,它会被迫使用 UTF-8,因为这是 BOM 的含义。
解决问题的全局方法
将 -Dfile.encoding=UTF-8
添加到您的 ColdFusion JVM。可以在此处添加参数:/cfusion/bin/jvm.config
(行:java.args=
)
这需要重新启动 ColdFusion 才能恢复。然后,您的所有文件都可以保存为简单的 UTF-8(无 BOM)格式,这样就可以正常工作了。
当我 运行 服务器上的以下代码 运行ning ColdFusion 2018:
<cfsetting enablecfoutputonly="yes">
<cfxml variable="test">
<cfoutput>
<test>
áéíóú
</test>
</cfoutput>
</cfxml>
<cfset testString = ToString(test)>
<cfset testStringISO = Replace(testString, "UTF-8", "iso-8859-1")>
<cffile action="write" file="#AbsoluteFilesPath#test.xml" output="#testStringISO#" charset="iso-8859-1">
其中 AbsoluteFilesPath
是对服务器上某个位置的绝对引用。找到了我用来更改 XML 编码的方法 here。当我在服务器上用 Notepad++ 打开 test.xml
文件时,它看起来像这样:
<?xml version="1.0" encoding="iso-8859-1"?>
<test>
αινσϊ
</test>
文件的编码显示为“ISO 8859-7”。
有趣的是,在我的本地机器上用 VSCode 打开文件显示如下:
<?xml version="1.0" encoding="iso-8859-1"?>
<test>
�����
</test>
这里,文件的编码显示为“UTF-8”。在编辑器中选择命令“使用编码 ISO 8859-1 重新打开”显示文件应该是这样的:
<?xml version="1.0" encoding="iso-8859-1"?>
<test>
áéíóú
</test>
我测试了这段代码,将“iso-8859-1”替换为“utf-16”,结果是一样的。
为什么文件编码不一致,不是我想要的?如何确保使用正确的编码创建文件?
让我们先澄清一点:XML 文件中的 encoding
属性只是 reader 的一个指标。它不影响写入实际文件的字节。
所以让我们将示例代码简化为单个字符 á
:
UTF-8 存储 2 个字节,ISO-8859-1 存储 1 个字节。这就是我们所期望的。
示例代码
<cfsetting enablecfoutputonly="true">
<cfxml variable="test">
<cfoutput><r>á</r></cfoutput>
</cfxml>
<cfset xmlForUTF = toString(test)>
<cfset xmlForISO = replace(xmlForUTF, 'encoding="UTF-8"', 'encoding="ISO-8859-1"')>
<cfset fileWrite(expandPath("UTF-8.xml"), xmlForUTF, "UTF-8")>
<cfset fileWrite(expandPath("ISO-8859-1.xml"), xmlForISO, "ISO-8859-1")>
生成的文件
UTF-8.xml
ISO-8859-1.xml
这正是我们所期望的。 cfxml
和 cffile
/fileWrite
都不是问题。 那么为什么在您的机器上使用上述代码可能得不到相同的结果?
问题:页面编码
ColdFusion在解析模板文件(.cfm
)和组件文件(.cfc
)时,会使用JVM的默认编码,如无特别说明,即为系统默认编码。这也是为什么每个人用上面的代码得到不同结果的原因。
如果文件中有诸如 á
之类的文字,则此字符将使用您告诉文本编辑器使用的任何内容进行编码。我们假设是 UTF-8
。如果您检查该文件,您将看到该字符已正确存储。然而,当 ColdFusion 打开这个文件并解析文字时,它会假定该字符使用系统的默认编码进行编码。不幸的是,您似乎 运行 一个不使用或不能使用 UTF-8 作为系统范围代码集的系统(例如 Windows)。
解决方案
一种(丑陋的)解决方法
解决它的(hacky)方法
将 ColdFusion 使用其解析器处理的每个文件(所有 .cfm
/.cfc
文件)保存为 UTF-8 和 BOM。当 ColdFusion 在文件开头遇到这些字节时,它会被迫使用 UTF-8,因为这是 BOM 的含义。
解决问题的全局方法
将 -Dfile.encoding=UTF-8
添加到您的 ColdFusion JVM。可以在此处添加参数:/cfusion/bin/jvm.config
(行:java.args=
)
这需要重新启动 ColdFusion 才能恢复。然后,您的所有文件都可以保存为简单的 UTF-8(无 BOM)格式,这样就可以正常工作了。