在XML中发送非标准字符

时间:2013-06-04 11:42:43

标签: java xml character-encoding

我正在调试第三方网关系统,它将二进制消息转换为XML Web服务。收到包含特殊字符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]

3 个答案:

答案 0 :(得分:1)

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

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

答案 1 :(得分:1)

您无法直接在XML文档中传输二进制数据 - 例如,没有有效的方法可以使ASCII为零。

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

答案 2 :(得分:0)

首先,使用

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是欧元字符。