繁体   English   中英

将字节转换为字符串的方法

[英]ways to convert bytes to STring

我正在使用以下代码使用 Java 从 IBM MQ 读取消息。

public void asyncReadMessage() 
    {
        System.out.println("inside asyncReadmessage");
        
            
        try{
            
            com.ibm.mq.MQQueue defaultLocalQueue;
            MQQueueManager qManager=null;
            String strMessage=null;
            MQEnvironment.hostname = "reese.int.westgroup.com";
            MQEnvironment.channel = "CLIENTCONNECTION";
            MQEnvironment.port = 1414;
            String qMngrStr = "";
            qManager = new MQQueueManager(qMngrStr); 
            int openOptions = MQC.MQOO_FAIL_IF_QUIESCING |
                    MQC.MQOO_INPUT_SHARED | MQC.MQOO_BROWSE;
                    //| MQC.MQOO_INQUIRE ; 
            String queueName="COMSERV.SRCHEXT.EVENTS.PUBLISH.QA.Q01";
            System.out.println("accessing::"+queueName);
            defaultLocalQueue = qManager.accessQueue(queueName, openOptions);
            //set transport properties.
            System.out.println("set MQ props");
            MQEnvironment.properties.put(MQC.TRANSPORT_PROPERTY, MQC.TRANSPORT_MQSERIES_CLIENT);
            System.out.println("new Queuemanager");
            ArrayList<String> msglist=new ArrayList<String>();
            boolean getMore = true;
            String messageText = null;
            while(getMore)
            {  
            MQMessage getMessages = new MQMessage();
            MQGetMessageOptions gmo = new MQGetMessageOptions();
            gmo.options=MQC.MQGMO_WAIT | MQC.MQGMO_BROWSE_FIRST;
            gmo.matchOptions=MQC.MQMO_NONE;
            gmo.waitInterval=100000;
            defaultLocalQueue.get(getMessages, gmo);
            int length=getMessages.getMessageLength();
            byte[] bMsg = new byte[length];
            getMessages.readFully(bMsg);
            String retrievedmsg = new String(bMsg);
            System.out.println("retrievedmsg::"+retrievedmsg);
           
            if(!(retrievedmsg.equals("")))
            {
                MessageHandler mh = new MessageHandler();
                System.out.println("messagehandler java file:"+retrievedmsg);
                mh.processMessages(retrievedmsg);
            }
            msglist.add(retrievedmsg);
            System.out.println("msglist::"+msglist.toString());
            }
            if(defaultLocalQueue.getCurrentDepth()==0)
             {
                getMore=false;
             }
            /*for (String message : msglist)
            {
                System.out.println("message in for loop::"+message);
                MessageHandler mh = new MessageHandler();
                System.out.println("messagehandler java file:"+message);
                mh.processMessages(message);
            }*/
            }
            
            catch(Exception e)
            {
                e.printStackTrace();
            }
    }

当我打印“retrievedmsg”变量时,它被打印为“< maestro . process s. event”。 相反,它应该填充为“<maestro.process.event”。 而且,如果我尝试从 Catalina 日志文件中复制“< maestro . process . event”并将其粘贴到记事本中,那么只会复制它的第一个字母,而不会复制其他字母。 看起来它正在读取一个字节。 如果我错了,请纠正我。 请帮助如何实现这一目标。

尝试String retrievedmsg = new String(bMsg, StandardCharsets.UTF_8)

有很多方法可以将字节解释为文本。 在字节和文本之间转换的每个方案都称为Charset

当您编写new String(bMsg)您正在使用系统的默认字符集转换 bMsg 的字节。 您收到的字节似乎不在该字符集中。

每当您尝试在字节和文本之间进行转换时,您都需要了解字符集。 使用new String(byte[])不会使问题消失,它只是意味着您忽略了该问题,这将带来危险,正如您在本例中所看到的。

我的猜测是您系统的默认字符集是一字节字符集,如 ISO-8859-1 或 windows-1252,它们期望一个字节代表一个字符,但您收到的文本是小端 UTF-16,它使用两个字节来表示每个字符。 如果是这种情况,您可以通过指定该字符集来解决它:

String retrievedmsg = new String(bMsg, StandardCharsets.UTF_16LE);

但是,仅此一项并不是解决方案。 您需要从消息提供者那里了解他们是否会始终以 UTF-16LE 格式发送消息。 如果不知道用于传输数据的字符集,您就无法知道如何将字节转换为文本。

MQEnvironment.hostname = "reese.int.westgroup.com"; String queueName="COMSERV.SRCHEXT.EVENTS.PUBLISH.QA.Q01";

您应该始终用虚拟值替换私人内部公司值。

其次,您应该使用 Hashtable 而不是 MQEnvironment 类。 只需阅读我在 StackOverflow 上发布的任何 Java/MQ 示例。 MQTest11.java

“< maestro . process s. event”

这看起来像 Windows 双字节又名字符集 1252。这不是 MQ 问题,而是 Java 转换问题。 你尝试了什么? 您是否尝试按照 VGR 或 rsampaths16 建议在“新字符串”上指定字符集。

IE

String retrievedMsg = new String(bMsg, "cp1252");

最后,为什么不在 HEX 转储中输出消息有效负载? 这样你就可以确切地知道你在处理什么。

如果您不知道该怎么做,那么这里有一些示例 Java 代码可以帮您完成。 将其放入您的工具包中,以便您可以轻松地将其添加到任何项目中

/**
 * Dump a byte array as a standard HEX dump output
 * @param data the entire byte array
 * @param widthSize width of the HEX dump. Must be in multiples of 16
 */
public void dumpBuffer(byte[] data, int widthSize)
{
   int endPt = widthSize;
   int len = data.length;
   byte[] tempB = new byte[widthSize];

   if (widthSize == 16)
   {
      System.out.println("Address  0 1 2 3  4 5 6 7  8 9 A B  C D E F  0123456789ABCDEF");
      System.out.println("------- -------- -------- -------- --------  ----------------");
   }

   for (int i=0; i < len; i+=widthSize)
   {
      if (i+widthSize >= len)
         endPt = len - i;

      for (int j=0; j < endPt; j++)
         tempB[j] = data[i+j];

      System.out.println(formatHex(tempB, (i+widthSize < len?widthSize:len-i), i, widthSize ));
   }
}

/**
 * Format an array of bytes into a hex display
 * @param src a portion of the byte array
 * @param len length of this part of the byte array
 * @param index location of current position in data
 * @param width width of the HEX dump
 * @return
 */
private String formatHex(byte[] src, int lenSrc, int index, int width)
{
   String HEX = "0123456789ABCDEF";
   int i,j;
   int g = width / 4; /* number of groups of 4 bytes */
   int d = g * 9;     /* hex display width */
   StringBuffer sb = new StringBuffer();

   if ( (src == null) ||
        (lenSrc < 1) || (lenSrc > width) ||
        (index < 0) ||
        (g % 4 != 0) ||   /* only allow width of 16 / 32 / 48 etc. */
        (d < 36) )
   {
      return "";
   }

   String hdr = Integer.toHexString(index);
   if (hdr.length() <= 6)
      sb.append("000000".substring(0, 6 - hdr.length()) + hdr + ": ");
   else
      sb.append(hdr + ": ");

   /* hex display 4 by 4 */
   for(i=0; i < lenSrc; i++)
   {
      sb.append(""+HEX.charAt((src[i]) >> 4) + HEX.charAt((src[i] & 0x0F)));

      if (((i+1) % 4) == 0)
         sb.append(" ");
   }

   /* blank fill hex area if we do not have "width" bytes */
   if (lenSrc < width)
   {
      j = d - (lenSrc*2) - (lenSrc / 4);
      for(i=0; i < j; i++)
         sb.append(" ");
   }

   /* character display */
   sb.append(" ");
   for (i=0; i < lenSrc; i++)
   {
      if(Character.isISOControl((char)src[i]))
         sb.append(".");
      else
         sb.append((char)src[i]);
   }

   /* blank fill character area if we do not have "width" bytes */
   if (lenSrc < width)
   {
      j = width - lenSrc;
      for(i=0; i < j; i++)
         sb.append(" ");
   }

   return sb.toString();
}

要使用此代码,只需执行以下操作:

dumpBuffer(bMsg, 16);

其中 bMsg 是代码从队列中检索到的消息。 十六进制转储看起来像:

Address  0 1 2 3  4 5 6 7  8 9 A B  C D E F  0123456789ABCDEF
------- -------- -------- -------- --------  ----------------
000000: 54686973 20697320 61207465 7374206D  This is a test m
000010: 65737361 67652061 6E642061 6E6F7468  essage and anoth
000020: 65722065 7863656C 6C656E74 20657861  er excellent exa
000030: 6D706C65 20627920 526F6765 722C2069  mple by Roger, i
000040: 66204920 646F2073 61792073 6F206D79  f I do say so my
000050: 73656C66 21212020 3A29               self!!  :)      

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM