2013-05-17 79 views
2

我們有一個通過MQ與外部通信的過程。外部系統在大型機上運行(IBM z/OS),同時我們在CentOS Linux平臺上運行我們的過程。到目前爲止,我們從未遇到任何問題是UTF to EBCDIC轉換無損?

最近我們開始接收消息,消息中嵌入了不可打印的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("----------------------------------------------------------------"); 
} 
+1

'new String(subStringBytes);' - 這是使用您的默認編碼。你知道它是什麼嗎?你知道它支持你可能獲得的所有可能的字節組合,並且你知道它是否可逆嗎? – parsifal

+0

此外,「UTF」沒有後綴沒有意義。你在說「UTF-8」嗎?如果是這樣的話,那麼答案顯然是否定的,因爲不是所有的字節序列在[UTF-8](http://en.wikipedia.org/wiki/UTF-8)中都是合法的 - 包括似乎是前三個字節的消息。 – parsifal

+0

MQ中的CCSID 1208對應於UTF-8(http://www-01.ibm.com/software/globalization/ccsid/ccsid_registered.html)。當你說並非所有的字節序列都是合法的,你的意思是因爲UTF-8是可變寬度? –

回答

1

如果MQ消息有不同的子消息字段,需要不同的編碼,那麼這就是你應該如何處理這些消息,即作爲separa te消息片斷。

但正如你所描述的那樣,整個消息需要在沒有轉換的情況下被接收。前八個字節需要分開提取和保存。消息的其餘部分可以轉換其編碼(除非其他子字段也需要被提取爲二進制,未轉換的字節)。

對於任何返回消息,必須完成相反的轉換。消息的文本部分可以被轉換,然後該子字符串可以將原始的八個字節添加到該字符串中。然後新重建的消息可以通過隊列發回,而不用自動轉換。

另一端的夥伴未正確使用消息產品。 (當然,你可能不應該大聲說出來。)不應該有這樣的消息的一部分,不能自動地在兩個方向上完整地保留下來。對於一個示例方法,應該將它表示爲更像是8字節值的16字節十六進制表示形式的一個8字節二進制字段。在十六進制中,路線上不會出現任何轉換問題。

+0

我們結束了逐字節轉換。該消息被轉換爲UTF-8,但隨後EBCDIC轉換丟失。我們最終使用從UTF-8到ASCII變體的轉換,然後返回到EBCDIC。 –

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中的不同字符。因此,你提出的處理方式將是非常危險和容易出錯的。