【发布时间】:2013-05-17 17:03:04
【问题描述】:
我们有一个通过 MQ 与外部通信的进程。外部系统在大型机机器(IBM z/OS)上运行,而我们在 CentOS Linux 平台上运行我们的进程。到目前为止,我们从未遇到任何问题。
最近我们开始接收来自他们的消息,其中嵌入了不可打印的 EBCDIC 字符。他们使用字符作为压缩 ID,长度为 8 个字节。当我们收到它时,它会到达以 UTF (CCSID 1208) 编码的队列。
为了识别我们的响应消息,它们需要返回原始 8 个字节。我正在尝试在 Java 中找到一种解决方案,以便在发送响应之前将 ID 从 UTF 转换回 EBCDIC。
我一直在使用 JTOpen 库,使用 AS400Text 类进行转换。此外,交易对手已向我们发送了 ID 的快照(以字节为单位)。但是,当我比较转换后的字节时,它们与原始消息不同。
有人遇到过这个问题吗?也许我使用了错误的代码页?
感谢您的任何意见。
来自交易对手的字节数(位置 [5,14]):
00000 F0 40 D9 F0 F3 F0 CB 56--EF 80 04 C9 10 2E C4 D4 |0 R030.....I..DM|
程序输出:
UTF String: [R030ôîÕØœIDMDHP1027W 0510]
EBCDIC String: [R030ôîÃÃÂIDMDHP1027W 0510]
NATIVE CHARSET - HEX: [52303330C3B4C3AEC395C398C29C491006444D44485031303237572030353130]
CP500 CHARSET - HEX: [D9F0F3F066BE66AF663F663F623FC9102EC4D4C4C8D7F1F0F2F7E640F0F5F1F0]
这里是一些示例代码:
private void readAndPrint(MQMessage mqMessage) throws IOException {
mqMessage.seek(150);
byte[] subStringBytes = new byte[32];
mqMessage.readFully(subStringBytes);
String msgId = toHexString(mqMessage.messageId).toUpperCase();
System.out.println("----------------------------------------------------------------");
System.out.println("MESSAGE_ID: " + msgId);
String hexString = toHexString(subStringBytes).toUpperCase();
String subStr = new String(subStringBytes);
System.out.println("NATIVE CHARSET - HEX: [" + hexString + "] [" + subStr + "]");
// Transform to EBCDIC
int codePageNumber = 37;
String codePage = "CP037";
AS400Text converter = new AS400Text(subStr.length(), codePageNumber);
byte[] bytesData = converter.toBytes(subStr);
String resultedEbcdicText = new String(bytesData, codePage);
String hexStringEbcdic = toHexString(bytesData).toUpperCase();
System.out.println("CP500 CHARSET - HEX: [" + hexStringEbcdic + "] [" + resultedEbcdicText + "]");
System.out.println("----------------------------------------------------------------");
}
【问题讨论】:
-
new String(subStringBytes);- 这是使用您的默认编码。你知道它是什么吗?你知道它支持你可能得到的所有可能的字节组合吗?你知道它是否可逆吗? -
另外,“UTF”没有后缀是没有意义的。你说的是“UTF-8”吗?如果是这种情况,那么答案显然是否定的,因为并非所有字节序列在 UTF-8 中都是合法的——包括消息的前三个字节。
-
MQ 中的 CCSID 1208 对应于 UTF-8 (www-01.ibm.com/software/globalization/ccsid/…)。当您说并非所有字节序列都是合法的时,您的意思是因为 UTF-8 是可变宽度的吗?
-
不仅是可变宽度,而且高位是有意义的(因此我喜欢维基百科页面)。您显示的“MESSAGE_ID”以
C3E2开头,这是一个无效的 UTF-8 序列:C3是双字节序列的开头,但E2不是有效的第二个字节;它仅作为 3 字节序列的第一个字节有效。 -
我想再次指出
new String(subStringBytes)使用您的平台默认编码。也许这对你来说是 UTF-8,也许不是。更糟糕的是,它可能对您来说是 UTF-8,而不是在您用于部署的任何平台上的 UTF-8。