UTF到EBCDIC转换是否无损?

时间:2013-05-17 17:03:04

标签: java ibm-mq ebcdic

我们有一个通过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("----------------------------------------------------------------");
}

2 个答案:

答案 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中的不同字符。因此,您建议的处理方式将非常危险并且容易出错。