java - 我有 UTF-8 - 但仍然得到 "Invalid byte 1 of 1-byte UTF-8 sequence"

标签 java xml encoding utf-8 xerces

我即时创建了一个 XML 字符串(不是从文件中读取)。然后我使用 Cocoon 3 通过 FOP 将其转换为 PDF。 Xerces 在中间某处运行。当我使用硬编码的东西时,一切正常。一旦我将德语变音符号放入数据库并使用该数据丰富我的 xml,我就会得到:

Caused by: org.apache.cocoon.pipeline.ProcessingException: Can't parse the XML string.
at org.apache.cocoon.sax.component.XMLGenerator$StringGenerator.execute(XMLGenerator.java:326)
at org.apache.cocoon.sax.component.XMLGenerator.execute(XMLGenerator.java:104)
at org.apache.cocoon.pipeline.AbstractPipeline.invokeStarter(AbstractPipeline.java:146)
at org.apache.cocoon.pipeline.AbstractPipeline.execute(AbstractPipeline.java:76)
at de.grobmeier.tab.webapp.modules.documents.InvoicePipeline.generateInvoice(InvoicePipeline.java:74)
... 87 more

Caused by: com.sun.org.apache.xerces.internal.impl.io.MalformedByteSequenceException: Invalid byte 1 of 1-byte UTF-8 sequence.
    at com.sun.org.apache.xerces.internal.impl.io.UTF8Reader.invalidByte(UTF8Reader.java:684)
    at com.sun.org.apache.xerces.internal.impl.io.UTF8Reader.read(UTF8Reader.java:554)

然后我调试了我的应用程序并发现,我的“Ä”(来自数据库)的字节值为 196,即十六进制的 C4。这是我所期望的:http://www.utf8-zeichentabelle.de/

我不知道为什么我的代码会失败。

然后我尝试像这样手动添加 BOM:

byte[] bom = new byte[3];
bom[0] = (byte) 0xEF;
bom[1] = (byte) 0xBB;
bom[2] = (byte) 0xBF;
String myString = new String(bom) + inputString;

我知道这不太好,但我试过了 - 当然失败了。我尝试在前面添加一个xml header :

<?xml version="1.0" encoding="UTF-8"?>

也失败了。然后我结合了它。失败。

毕竟我尝试过类似的东西:

xmlInput = new String(xmlInput.getBytes("UTF8"), "UTF8");

实际上什么都不做,因为它已经是 UTF-8。还是失败了。

那么...知道我做错了什么以及 Xerces 对我的期望是什么吗?

谢谢 基督徒

最佳答案

如果您的数据库只包含一个字节(值为 0xC4),那么您没有使用 UTF-8 编码。

字符“带分音符的拉丁文大写字母 A”的代码点值为 U+00C4,但 UTF-8 无法将其编码为单个字节。如果您检查 UTF8-zeichentabelle.de 上的第三列“UTF-8(十六进制)”,您会看到 UTF-8 将其编码为 0xC3 84(两个字节)。

请阅读 Joel 的文章“The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!)”了解更多信息。


编辑:克里斯蒂安自己找到了答案;原来这是 Cocoon 3 SAX 组件中的一个问题(我猜这是 alpha 3 版本)。事实证明,如果您将 XML 作为字符串传递给 XMLGenerator 类,SAX 解析过程中就会出现问题,从而导致这种困惑。

looked up the code在 Cocoon-stax 中找到实际问题:

if (XMLGenerator.this.logger.isDebugEnabled()) {
    XMLGenerator.this.logger.debug("Using a string to produce SAX events.");
}
XMLUtils.toSax(new ByteArrayInputStream(this.xmlString.getBytes()), XMLGenerator.this.getSAXConsumer();

如您所见,调用 getBytes() 将使用 JRE 的默认编码创建一个 Byte 数组,然后将无法解析。这是因为 XML 声明自己为 UTF-8,而数据现在再次以字节为单位,并且可能使用您的 Windows 代码页。

作为一种解决方法,可以使用以下方法:

new org.apache.cocoon.sax.component.XMLGenerator(xmlInput.getBytes("UTF-8"),
       "UTF-8");

这将触发正确的内部操作(正如 Christian 通过试验 API 发现的那样)。

我已经 opened an issue在 Apache 的错误跟踪器中。

编辑 2:该问题已修复并将包含在即将发布的版本中。

关于java - 我有 UTF-8 - 但仍然得到 "Invalid byte 1 of 1-byte UTF-8 sequence",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8471816/

相关文章:

javascript - 用Java对Http请求进行编码和解码

xml - 如何在 C# 中删除 XML 文档中的空格

java - 转换为 Ascii 失败 &

java - 在 Windows 2008 R2 Box 上创建 Jenkins Slave

java - Java中删除String[]

php 输出 xml 产生解析错误 "&rsquo;"

Android 应用程序未连接到 Wifi,但在通过 Wifi 共享的 3G 中工作正常

Android 4.0 html 编码在 web View 中崩溃

java - ArrayList 与 HashSet 中的 removeAll()

java - 循环不断覆盖java中mongodb更新("$max")的值