【问题标题】:Get MQ messageId in string format获取字符串格式的MQ messageId
【发布时间】:2018-01-25 12:32:07
【问题描述】:

我正在使用 IBM 的 mq 库从 MQ 队列中读取消息。现在我需要检索消息的 messageid。我现在它位于名称 messageId 下的消息头中。但这会返回一个字节[]。现在我需要将其更改为可读的字符串。

如何将 messageId 从 byte[] 转换为字符串?

我尝试了几次转换,但都不起作用:

new String(theMessage.messageId)
new String(theMessage.messageId, "UTF-8")
new String(theMessage.messageId, "UTF-16")
theMessage.messageId.toString()

【问题讨论】:

    标签: java ibm-mq


    【解决方案1】:

    MQMD 中的 messageId 表示为 24 个字节。如果您知道这些是在什么平台上生成的,那么您可以通过将字节转换为生成它们的队列管理器的字符集中的字符来为它们的某些部分找到一些含义,但不建议依赖任何正在传送的数据在 messageID 中作为字符数据,因为我看到来自 IBM 的类似“MsgId 由 MQ 以 IBM 专有格式生成的语句,它可能随时更改。”

    如果你想将它们表示为一个字符串,你应该将它们表示为一个代表 24 个字节的 48 个字符的 HEX 字符串。

    以下是 IBM 在技术说明中提供的示例函数 getHexString,它将为您执行此转换。你可以这样使用它:

    getHexString(theMessage.messageId)
    

    以下示例函数来自 IBM MQ 技术说明“How to match correlation id's when request is made via JMS application and reply generated from base Java API

    public static String getHexString(byte[] b) throws Exception {
        String result = "";
        for (int i=0; i < b.length; i++) {
            result += Integer.toString( ( b[i] & 0xff ) + 0x100, 16).substring( 1 );
        }
        return result;
    }
    

    IBM 在知识中心页面“Reference>Developing applications reference>MQI applications reference>Data types used in the MQI>MQMD - Message descriptor>Fields>MsgId (MQBYTE24)”底部记录了队列管理器生成的消息 ID 的格式和唯一性

    队列管理器生成的 MsgId 包含一个 4 字节的产品标识符(ASCII 或 EBCDIC 中的 AMQ¬ 或 CSQ¬,其中 ¬ 表示空白字符),后跟唯一字符串的特定于产品的实现。在 IBM® MQ 中,它包含队列管理器名称的前 12 个字符,以及从系统时钟派生的值。因此,所有可以相互通信的队列管理器必须具有前 12 个字符不同的名称,以确保消息标识符是唯一的。生成唯一字符串的能力还取决于系统时钟不会向后更改。为了消除队列管理器生成的消息标识符与应用程序生成的消息标识符重复的可能性,应用程序必须避免生成具有 ASCII 或 EBCDIC(X'41' 到 X'49' 和X'C1' 到 X'C9')。但是,不会阻止应用程序生成具有这些范围内的初始字符的标识符。

    【讨论】:

      【解决方案2】:

      我已经成功实现了获取 MQ MessageId 并将其转换为十六进制字符串以进行本地存储,然后在稍后使用它再次查询 MQ 时将其转换回字节 [] 的循环,使用 Apache Commons Codec 因此:

      import org.apache.commons.codec.binary.Hex;
      
      String mqMessageId = Hex.encodeHexString(message.messageId);
      message.messageId = Hex.decodeHex(mqMessageId.toCharArray());
      

      我喜欢这种方法,因为它依赖于来自知名和受人尊敬的组织的维护良好的库,而且我不需要维护任何其他方法。

      尽管如此,我还是要感谢上面 Roger 的 cmets,因为他们让我走上了通往 Apache Commons Codec 的道路。

      【讨论】:

        【解决方案3】:

        MQMD MessageId 字段由字符值和二进制值组成。因此,将 MessageId 字段正确表示为 String 的唯一方法是将其转换为 HEX 表示。

        你需要使用我的 bytesToHex 方法:

        String s = bytesToHex(theMessage.messageId);
        

        因此,s 看起来像“414D51204D5141312020202020202020134CCD4020000B01”。

        bytesToHex 方法的Java代码是:

        public static final String HEX_CHARS = "0123456789ABCDEF";
        
        public static String bytesToHex(byte[] data)
        {
           StringBuffer buf = new StringBuffer();
           for (int i = 0; i < data.length; i++)
              buf.append(byteToHex(data[i]));
        
           return buf.toString();
        }
        
        public static String byteToHex(byte data)
        {
           int hi = (data & 0xF0) >> 4;
           int lo = (data & 0x0F);
           return "" + HEX_CHARS.charAt(hi) + HEX_CHARS.charAt(lo);
        }
        

        2020 年 7 月 23 日更新。

        这是一个将 HEX 字符串转换为字节数组的方法:

        public static byte[] hexStringToByteArray(String inString)
        {
           byte[] outBuffer = new byte[inString.length()/2];
           String hex;
           int xx;
        
           for (int i=0, j=0; j < (inString.length() - 1); i++, j+=2)
           {
              hex = inString.substring(j,j+2);
              xx = Integer.parseInt(hex.trim(), 16);
              if (xx < 0)
                 xx += 256;
        
              outBuffer[i] = (byte)xx;
           }
        
           return outBuffer;
        }
        

        【讨论】:

        • 如果我将 messageId 发送回 MQ 以定位消息,是否需要将其从十六进制转换回字节?
        • 是的。 MessageId 是一个 24 字节的字段。
        • 谢谢罗杰!你熟悉这里提到的 Apache Codec 类吗:stackoverflow.com/a/140147/2784931
        • 我正在考虑使用 Codec 类在两端进行翻译。
        • 对不起。我没有使用过 Apache 编解码器。我更新了我的答案以包括我的 hexStringToByteArray() 方法。
        猜你喜欢
        • 1970-01-01
        • 2014-09-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-11-27
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多