gpt4 book ai didi

java - Xerces UTF8Reader 中导致 MalformedByteSequenceException 的编码问题

转载 作者:数据小太阳 更新时间:2023-10-29 02:02:03 25 4
gpt4 key购买 nike

我遇到了 com.sun.org.apache.xerces.internal.impl.io.MalformedByteSequenceException使用 XML 文件。我使用调试器逐步执行 Xerces 代码,并缩小了发生这种情况的范围。我能够确定通过删除文档中的“智能引号”字符,文档变得可解析。

文档没有 DTD。 Notepad++ 将其标记为“作为 UTF-8 的 ANSI”。 Firefox 将其称为“西方”。我记得在大学里听过一次不太惊心动魄的讲座,UTF-8 被设计为与单字节编码系统向后兼容。我也看到 on this chart , 字节序列 e2 80 9d事实上,代表“右双引号”,但即使我看不到编码问题,我认为还是有一个。

我从 Xerces 收到的异常消息是 Invalid byte 3 of 3-byte UTF-8 sequence.它从 invalidByte(3, 3, b2) 中被抛出调用 UTF8Reader 的第 435 行.当我试图完全理解这种方法的逻辑时,我的大脑开始有点融化,所以我可能会遗漏一些东西,但正如我上面提到的字节 3 (0x90)。根据 UTF-8 表,至少上面的序列是有效的。

这是在十六进制编辑器中显示的双引号所在的文件段:XML segment

我尝试了以下方法:

  • 通过 Charset.forName("UTF-8") 使用 UTF-8 强制加载字符串
  • 添加 DTD <?xml version="1.0" encoding="UTF-8"?>
  • 在 Notepad++ 中打开文件并通过其 UI 将其编码为 UTF-8
  • 上述的各种组合,有时反复

指示为无效的字节似乎是 63(0x3F?) eclipse screenshot

我还尝试将这个智能引号字符添加到以前可解析的文档中。正如预期的那样,它使解析器抛出相同的异常。

堆栈跟踪:

com.sun.org.apache.xerces.internal.impl.io.MalformedByteSequenceException: Invalid byte 3 of 3-byte UTF-8 sequence.
at com.sun.org.apache.xerces.internal.impl.io.UTF8Reader.invalidByte(UTF8Reader.java:687)
at com.sun.org.apache.xerces.internal.impl.io.UTF8Reader.read(UTF8Reader.java:435)
at com.sun.org.apache.xerces.internal.impl.XMLEntityScanner.load(XMLEntityScanner.java:1753)
at com.sun.org.apache.xerces.internal.impl.XMLEntityScanner.skipChar(XMLEntityScanner.java:1426)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:2815)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:606)
at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.next(XMLNSDocumentScannerImpl.java:117)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:510)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:848)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:777)
at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:141)
at com.sun.org.apache.xerces.internal.parsers.DOMParser.parse(DOMParser.java:243)
at com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl.parse(DocumentBuilderImpl.java:347)
at javax.xml.parsers.DocumentBuilder.parse(DocumentBuilder.java:121)

...

更新:我仍然需要找到一种方法将其安全地转换为字符串。我使用 Notepad++ 将文件编码为 UTF-8。下面的代码成功地将字节加载到一个字符串中(我可以看到在 Eclipse 中调试时读取字符串中的 XML),但现在我得到了带有不同参数的 MalformedByteSequenceException。这次,我可以同时发布代码和 XML我正在使用:

File file = new File("ccd.xml");

byte[] ccdBytes = org.apache.commons.io.FileUtils.readFileToByteArray(file);
String ccdString = new String(ccdBytes, Charset.forName("UTF-8"));

CDAUtil.load(new ByteArrayInputStream(IOUtils.toByteArray(ccdString))); //method that's doing the parsing

堆栈跟踪:

Exception in thread "main" 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:687)
at com.sun.org.apache.xerces.internal.impl.io.UTF8Reader.read(UTF8Reader.java:557)
at com.sun.org.apache.xerces.internal.impl.XMLEntityScanner.load(XMLEntityScanner.java:1753)
at com.sun.org.apache.xerces.internal.impl.XMLEntityScanner.skipChar(XMLEntityScanner.java:1426)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:2815)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:606)
at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.next(XMLNSDocumentScannerImpl.java:117)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:510)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:848)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:777)
at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:141)
at com.sun.org.apache.xerces.internal.parsers.DOMParser.parse(DOMParser.java:243)
at com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl.parse(DocumentBuilderImpl.java:347)
at javax.xml.parsers.DocumentBuilder.parse(DocumentBuilder.java:121)
at org.openhealthtools.mdht.emf.runtime.resource.impl.FleXMLLoadImpl.load(FleXMLLoadImpl.java:55)
at org.eclipse.emf.ecore.xmi.impl.XMLResourceImpl.doLoad(XMLResourceImpl.java:180)
at org.eclipse.emf.ecore.resource.impl.ResourceImpl.load(ResourceImpl.java:1494)
at org.openhealthtools.mdht.uml.cda.util.CDAUtil.load(CDAUtil.java:268)
at org.openhealthtools.mdht.uml.cda.util.CDAUtil.load(CDAUtil.java:250)
at org.openhealthtools.mdht.uml.cda.util.CDAUtil.load(CDAUtil.java:238)

但是,

CDAUtil.load(new FileInputStream(new File("ccd.xml")));

作品

最佳答案

您没有告诉我们您是如何将文件传递给 Xerces 的。你可以用不同的方式做不同的结果。您可以阅读有关 xml 编码问题的更详细说明 here

我建议您执行以下操作:

  1. 用 Notepad++ 打开文件并添加<?xml version="1.0"
    encoding="UTF-8"?>
    如果缺少,作为第一行
  2. 在 Notepad++ 中转换为 UTF-8(无 bom)(它应该在格式菜单中,但我使用的是意大利语版的 notepad++,所以我猜测菜单翻译)
  3. 保存文件
  4. 在 Java 中将其作为 InputStream 打开,即将 InputStream 和 NOT 作为 Reader 子类传递给 xml 解析器

这应该可以解决问题,如果您可以通过将文件传递给解析器的代码,则更容易找到问题。

这些步骤解决了问题,因为仅当您使用 InputStream(即字节流)时,解析器才会考虑带有编码声明的 xml 中的第一行。如果您读取字节流,则需要编码声明以指定如何将字节转换为字符。

如果您传递的是字符串,第一行是无用的,因为您传递的是字符流,不需要编码。

如果您想使用字符串,您必须将文件作为 InputStream 读取并转换为指定字符集的 Reader(类似于 InputStreamReader inputStreamReader= new InputStreamReader(xmlFileInputStream,"UTF-8"); )

我的猜测是您收到错误是因为您没有指定字符集,而 Java 选择了您的操作系统 (Windows-1252)。

关于java - Xerces UTF8Reader 中导致 MalformedByteSequenceException 的编码问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30676624/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com