【问题标题】:Sending non-standard characters in XML在 XML 中发送非标准字符
【发布时间】:2013-06-04 11:42:43
【问题描述】:

我正在调试一个第三方网关系统,它将二进制消息转换为 XML 网络服务。当它接收到包含特殊字符 0x80、0x81、0x82 和 0x83 的消息时会出现问题,它们不会以 XML 的形式正确发送。

我已将问题范围缩小到他们将 byte[] 转换为 String 的位置,并制作了一个简单的示例来说明问题所在。特殊值都被翻译成相同的“未知”字符。

public static void main(String[] args) {
    test(0x80);test(0x81);test(0x82);test(0x83);
}
public static void test(int value) {
    String message = new String(new byte[]{(byte)value});
    System.out.println(value + " => " + message + " => " + Arrays.toString(message.getBytes()));
}

输出

128 => � => [-17, -65, -67]
129 => � => [-17, -65, -67]
130 => � => [-17, -65, -67]
131 => � => [-17, -65, -67]

我想知道应该如何解决这个问题。我尝试更改他们的代码以使用显式字符集

new String(bytes, Charset.forName("UTF-8"))

但是这会导致同样的问题。值 0x80-0x83 似乎不作为有效的 XML entities 存在。

我发现你可以使用哪种类型的字符构造函数,但翻译以下内容,我不确定它是否正确??

new String(new char[]{(char) value}, 0, 1); 

输出

128 => weird box character 0080 => [-62, -128]
129 => weird box character 0081 => [-62, -127]
130 => weird box character 0082 => [-62, -126]
131 => weird box character 0083 => [-62, -125]

【问题讨论】:

    标签: java xml character-encoding


    【解决方案1】:

    您不能按字节将字节转换为 Java 字符串。您必须考虑二进制数据的编码。例如。 UTF-8 每个字符可以有不同的字节长度。

    UTF-8 & Unicode, what's with 0xC0 and 0x80?

    【讨论】:

      【解决方案2】:

      您不能直接在 XML 文档中传输二进制数据 - 例如,没有有效的方法来设置 ASCII 零。

      您需要将其编码为 ASCII 字符串(base64 或类似字符串)并传输,然后在接收端取消编码。

      【讨论】:

      • 它不必是 ASCII 字符串,而是 text 字符串,采用约定的编码(通常是 UTF-8,在 XML 的上下文中)。
      • 那么你可能想改写关于“二进制消息”的部分。
      【解决方案3】:

      首先,使用

      String message = new String(new byte[]{(byte)value});
      

      几乎总是错误的。要将byte[] 转换为String,您必须决定使用哪种字符编码。上面的代码将(不幸地)使用 JVM 默认编码进行转换,这取决于各种操作系统设置(如果用户更改这些设置,可能会随时更改)。在几乎所有情况下,您都希望明确指定编码。

      现在解决您的问题:

      我想知道应该如何解决这个问题。我试过改变他们的代码 使用显式字符集

      new String(bytes, Charset.forName("UTF-8"))

      但是这会导致同样的问题。

      这是正常的。您告诉 Java 将单字节序列“0x80”解释为 UTF-8。但是,这不是有效的 UTF-8 字符串。因此Java使用Unicode replacement character来表示错误。

      要解决这个问题,你必须找出你得到的数据中的“0x80”等意思。找出数据使用的字符编码,并使用该编码转换为String


      猜测:数据可能使用 Windows 编码 CP 1252(通常与 ISO 8859-1 混合)。在 CP 1252 中,0x80 是欧元字符。

      【讨论】:

        猜你喜欢
        • 2013-12-11
        • 2011-08-26
        • 1970-01-01
        • 1970-01-01
        • 2013-08-26
        • 1970-01-01
        • 2012-02-25
        • 2017-07-30
        • 1970-01-01
        相关资源
        最近更新 更多