我们有一个通过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("----------------------------------------------------------------");
}
答案 0 :(得分:1)
如果MQ消息具有需要不同编码的不同子消息字段,那么您应该如何处理这些消息,即作为单独的消息片段。
但正如您所描述的那样,需要在不进行转换的情况下接收整个消息。前八个字节需要分别提取和保存。然后,消息的其余部分可以转换其编码(除非其他子字段也需要提取为二进制,未转换的字节)。
对于任何返回消息,必须进行相反的转换。可以转换消息的文本部分,然后该子字符串可以包含前面的原始八个字节。然后,新重建的消息可以通过队列发回,同样没有自动转换。
另一端的合作伙伴未正确使用消息传递产品。 (当然,你可能不应该大声说出来。)这样的信息应该不会在两个方向上自动完好无损。对于一个示例方法,它应该表示为更像是8字节值的16字节十六进制表示,而不是8字节的二进制字段。在十六进制中,在整个路线上都没有转换问题。
答案 1 :(得分:0)
在我看来,特殊的8字节实际上不是EBCDIC字符,而只是8字节的数据。如果是这种情况,那么我相信,正如另一个答案所提到的,你应该分别处理这8个字节而不允许它转换为UTF8然后再回到EBCDIC进行进一步处理。
根据您使用的EBCDIC变体,很可能EBCDIC中的某个字节未转换为有意义的UTF-8字符,因此,您将无法通过将UTF8字符转换为EBCDIC来获取原始字节你收到。
对Google的简短搜索为我提供了几个EBCDIC表格(例如http://www.simotime.com/asc2ebc1.htm#AscEbcTables)。您可以看到EBCDIC中有许多未分配字符的值。因此,当它们转换为UTF8时,您可能不会假设它们中的每一个都将转换为Unicode中的不同字符。因此,您建议的处理方式将非常危险并且容易出错。