5

我正在为 Android 开发一个应用程序,我必须在其中解析不同的 XML 文件。它们中的大多数以 UTF-8 编码,但少数可能以 ISO-8859-1 编码。

  HttpURLConnection con = (HttpURLConnection) url.openConnection();
  ...
  in = con.getInputStream();
  InputSource is = new InputSource(in);
  ...
  parser.parse(is, handler);

我处理输入的代码如上所示。该java文档说InputSource

如果没有字符流,但有字节流,则解析器将使用该字节流,使用 InputSource 中指定的编码,否则(如果未指定编码)使用算法自动检测字符编码,例如XML 规范。

我传入 aByteStream并且我没有指定编码,因此根据文档,应该自动检测编码。但事实并非如此。所有以 UTF-8 编码的文件都很好,但 ISO-8859-1 的文件不是(我得到了一个Parser Expat... Exception for some invalid characters)。如果我将InputSource手动的编码设置为“ISO-8859-1”,它的行为则相反。

我该如何解决这个问题?我搜索了谷歌和Stackoverflow几个小时,但没有找到解决方案。我也尝试将 a 传递CharacterStream给,但ISO-8859-1 文件中的InputSource某些字符仍显示为“?” (äöüÄÖÜß)在我的应用程序中。

提前致谢!

4

4 回答 4

1

我建议检查是否有旧 ascii 集中没有的字符,如果似乎有 UTF-8 字符,则重新编码字符串:

String output=new String(input.getBytes("8859_1"), "utf-8");

该行采用 ISO-8859-1 并将其转换为 Java 使用的 utf-8。

于 2012-12-13T11:45:21.250 回答
1

最佳解决方案取决于问题的确切原因。如果您通过 HTTP 检索 XML 文档,则编码也可以在 Content-Type 响应标头中指定,而不必在 XML 文档本身中指定。如果是这种情况并且正确实现了 Android 中的 XML 库(我无法在此处检查是否评估了 Content+Type 标头),那么您应该能够直接使用 URL 创建一个 InputSource new InputSource("http://...");

如果编码未在 HTTP 标头中设置且未在 XML 序言中指定,则如果解析器采用 UTF-8 编码(如 XML 规范所要求的那样),则解析器将正确运行。文档中提到的自动检测并不意味着解析器实际上会查看文档内容以对编码做出假设,而是意味着它会检查 XML 流的编码属性。如果缺少 encoding 属性,则默认为 UTF-8。

于 2012-12-13T12:32:48.110 回答
0

最直接的方法是使用 UTF-8,如果抛出无效字节的解析器异常,请尝试将其重新解析为 Windows-1252。1252,因为我怀疑你会看到任何人使用 ISO-8859-1 C1 字符,而你会看到人们使用 Windows 1252 字符并声称它一直是 ISO-8859-1。

于 2012-12-13T11:13:08.400 回答
-1

我建议让 SAX 决定编码,它会从 XML 声明编码属性中知道

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

注意:如果没有合法的xml声明,则假定编码为UTF-8

如果您使用字节流 InputSource,如您的示例所示,并且不明确设置 InputStream 编码,则 SAX 将从 XML 获取编码

更新

试试这个测试。它将 xml 字符串写入 iso-8859-1 中的 1.xml 文件。然后 SAX 对其进行解析并打印根元素文本(它只有一个字符 'ä')。SAX 应该不理解 1.xmk 使用 iso-8859-1 否则输出会失真

String xml = "<?xml version='1.0' encoding='iso-8859-1'?><root>ä</root>";
OutputStreamWriter wrt = new OutputStreamWriter(new FileOutputStream(
        "1.xml"), "iso-8859-1");
wrt.write(xml);
wrt.close();
SAXParserFactory sf = SAXParserFactory.newInstance();
SAXParser p = sf.newSAXParser();
p.parse(new FileInputStream("1.xml"), new DefaultHandler() {
    public void characters(char[] ch, int start, int length)
            throws SAXException {
        System.out.println((int)ch[start]);
        System.out.println(String.valueOf(ch, start, length));
    }
});

查看输出

228
ä

它是正确的。SAX 无法理解 XML 编码 = 'iso-8859-1'。

于 2012-12-13T11:24:32.833 回答