[英]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.