我正在调试第三方网关系统,它将二进制消息转换为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]
答案 0 :(得分:1)
您无法按字节顺序将字节转换为Java字符串。您必须考虑二进制数据的编码。例如。 UTF-8每个字符可以有不同的字节长度。
答案 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是欧元字符。