【问题标题】:Encoding for unicode and & charactersunicode 和 & 字符的编码
【发布时间】:2016-04-01 07:34:10
【问题描述】:

我正在尝试将以下字符串保存到我的 protobuff 模型中:

STOXX®Europe 600 Food&BevNR ETF 

但在打印原型值时,它的显示如下:

STOXX®Europe 600 Food&BevNR ETF

我尝试将字符串编码为 UTF-8 并尝试StringEscapeUtils.unescapeJava(str),但失败了。我通过解析来自服务器的 XML 响应来获取这个字符串。有什么想法吗?

参考:XML 解析器Skip invalid xml element with XmlStreamReader

【问题讨论】:

  • 你从哪里得到这个字符串?
  • 我通过解析从 XML 中获取这个字符串。
  • 您应该更改 XML 解析器编码。请提供您的解析代码和 XML 文件(至少部分)
  • 这是我以 xml 形式从服务器获取的数据示例。

标签: java string encoding protocol-buffers


【解决方案1】:

纠正 XML 解析应该比需要取消转义所有内容要好。请检查下面的测试用例:

public static void main(String[] args) throws Exception {
    XMLInputFactory factory = XMLInputFactory.newInstance();
    factory.setProperty("javax.xml.stream.isCoalescing", true);
    ReaderInputStream ris = new ReaderInputStream(new StringReader("<tag>STOXX®Europe 600 Food&amp;BevNR ETF</tag>"));
    XMLStreamReader reader = factory.createXMLStreamReader(ris, "UTF-8");

    StringBuilder sb = new StringBuilder();
    while (reader.hasNext()) {
        reader.next();
        if (reader.hasText())
            sb.append(reader.getText());
    }

    System.out.println(sb);
}

输出:

STOXX®Europe 600 Food&BevNR ETF

【讨论】:

  • ® 只是特殊字符的一个示例。如果其他特殊字符来了怎么办?我需要一个通用的。
  • 在对字符串进行转义之前,您必须先修复 XML 解析的编码。
  • 尝试在阅读器xmlFactory.createXMLStreamReader(InputStream stream, String encoding)的编码中传递UTF-8
  • 但不幸的是,来自服务器的 xml 响应中包含文本 STOXX®
【解决方案2】:

其实我有 protobuf 方法来解决这个问题:

ByteString.copyFrom(StringEscapeUtils.unescapeHtml3(string), "ISO-8859-1").toStringUtf8();

Documentation of ByteString

【讨论】:

  • 这行得通的原因是:该字符串看起来像是 UTF-8 编码的,但使用 ISO-8859-1 显示。因此,将其解析为 ISO-8859-1(这只是将代码点转换为 1-on-1 字节),然后将其解码为 UTF-8 会反转该过程。
  • 哪种解决方案更好?更正 XML 解析还是这个?
  • 显然是前者。最好在读取数据时正确处理,而不是事后修补。
【解决方案3】:

由于文本来自 XML 使用:

s = StringEscapeUtils.unescapeXml(s);

这比具有数百个命名实体 &amp;...; 的非转义 HTML 要好得多。

这两个垃圾字符而不是版权符号是由于将 UTF-8 编码文本(特殊字符的多字节)读取为一些单字节编码,可能是 Latin-1。

这个错误的转换可能会通过另一个转换来修复,但最好是使用 UTF-8 编码来读取。

// Hack, just patching. Assumes Latin-1 encoding
s = new String(s.getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);
// Or maybe:
s = new String(s.getBytes(), StandardCharsets.UTF_8);

最好检查阅读代码,看看是否缺少可选的编码:InputStreamReader, OutputStreamWriter, new String, getBytes

使用 XML 阅读器也可以解决您的整个问题。

【讨论】:

    猜你喜欢
    • 2020-02-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多