java - 从WebSphere MQ消息检索时的字节长度差异

标签 java encoding character-encoding byte ibm-mq

在Java中,我正在轮询WebSphere MQ消息队列,期望消息为`STRING格式的消息,该消息完全由XML组成。该XML的一部分将包含文件附件的字节(任何格式:pdf,图像等),然后将其转换为blob以便存储在Oracle Db中,并在以后进行检索。

我遇到的问题是,发送过来的示例文件的已知大小最终以不同的大小出现在我的Db中。我没有在字节中添加任何内容(据我所知),并且在收到消息后大小似乎会更大。我无法确定我是否以某种方式在检索时添加信息,从bytes-> String进行转换,或者这是否发生在发件人填充邮件的前端。

我在检索消息时的代码:

              inboundmsg = new MQMessage();
              inboundmsg = getMQMsg(FrontIncomingQueue, gmo);
              strLen = inboundmsg.getMessageLength();
              strData = new byte[strLen];
              ibm_id = inboundmsg.messageId;
              inboundmsg.readFully(strData);
              inboundmsgContents = new String(strData);


我看到一个已知大小为21K的文件转到28K。一位同事建议字符集/编码可能是问题所在。从字符串转换回(用于其他无关的用途)时,我没有在上面的String的构造函数调用中或在对getBytes的任何调用中指定字符集。我的默认字符集是ISO-8859-1。与发起消息传输的供应商交谈时,我问她正在使用什么字符集。她的回复:

“我在C#中使用File.WriteAllBytes方法-我将文件的路径传递给它,并将其写入到byte []中。我在MSDN上找不到有关该函数使用什么编码的任何文档。该方法创建了一个字节数组,而我今天早上在网上阅读的内容都没有编码,只是一个没有编码的8位无符号二进制数据序列。”

另一位同事建议,也许是MQ字符集是罪魁祸首,但是我对文档的阅读表明,MQ字符集仅影响readStringreadLinewriteString的行为。

如果我完全规避MQ,并使用文件输入流和本地文件填充字节数组,则文件大小将一直保留到Db存储,因此,这肯定是在消息传输时或消息传输期间发生的。

最佳答案

问题在措词上很明显。您描述了一个包含任意二进制数据的有效负载,并且还尝试将其作为字符串处理。这两件事是互斥的。

由于供应商未提供有效的XML,这似乎变得很复杂。例如,考虑附件:

   <PdfBytes>iVBORw0KGgoAAAANS … AAAAASUVORK5CYII=</PdfBytes>


如果附件合法包含任何XML特殊字符(例如<>),则结果为无效XML。如果它包含空字节,则某些解析器会假定它们已到达文本的结尾并在此处停止解析。这就是为什么您通常会看到XML中的任何附件要么转换为Base64进行传输,要么转换为十六进制。

供应商描述了写入原始二进制数据的过程,这表明您收到的内容包含非字符串字符,因此不应作为字符串数据发送。如果她描述了某种转换,使附件XML兼容,那么字符串将是适当的。

有趣的是,Base64编码产生的有效负载是原始负载的1.33倍。巧合的是21k * 1.3 = 28k?有人会认为接收到的实际上是Base64格式的二进制有效负载。实际上,可以将其解析为字符串,并说明文件大小的差异。但这根本不是供应商所描述的。她说她正在写“没有编码的8位无符号二进制数据”,而不是Base64。

因此,我们希望它会失败,但不一定会导致更大的有效负载。考虑到接收到String格式消息的WebSphere MQ将尝试对其进行转换。如果消息的CCSID与GET上请求的消息不同,则MQ将尝试进行转换。如果入站CCSID为UTF-16或任何双字节字符集,则某些字符将从一字节扩展为两个字节-假定转换未遇到导致其失败的无效二进制字符。

如果两个CCSID相同,则在MQ类中不会尝试进行任何转换,但是仍然存在一个问题,就是必须解析XML负载,根据定义,该负载是无效的,因此可能会导致意外结果。如果碰巧二进制有效负载不包含任何XML特殊字符并且解析器没有阻塞任何嵌入的空字节,则解析器将使用相当长的长度来原谅不兼容的有效负载。如果它到达</PdfBytes>标记而没有阻塞,则可以假定有效负载是有效的,并转换<PdfBytes>...</PdfBytes>标记本身之间的所有内容。大概是Base64。

当然,所有这些都是推测。但是,在有效负载不是字符串数据明确无误的情况下,任何尝试对其进行解析的尝试都是因为字符串数据将彻底失败,或者产生意想不到的甚至潜在的奇怪结果。您实际上很不幸,它并没有彻底失败,因为现在可以预料,当问题显然是由供应商负责时,问题就在您的端上。

假设有效负载的内容保持不变,供应商应该发送bytes消息,而您应该以bytes的形式接收它们。至少可以解决MQ正在将预期格式与实际接收的格式进行协调的问题,但是它仍然是无效的XML。如果行得通,供应商将消息中的二进制数据发送为类型String,并且您将其作为bytes处理,那么请数数您的祝福并以这种方式使用它,但不要指望它是可靠的。最终,您将获得带有嵌入式XML特殊字符的有效负载,然后您将度过非常糟糕的一天。

理想情况下,供应商应该比在XML有效负载中发送二进制数据而不先将其转换为字符串更了解,并且由他们来修复它,以使其符合XML规范并可靠。

请参阅此MSDN页面:XML, SOAP, and Binary Data

关于java - 从WebSphere MQ消息检索时的字节长度差异,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26050143/

相关文章:

java - 事件驱动编程 - node.js、Java

java - JFreeChart 将数组加载到数据集中

delphi - 在 Delphi XE5 中使用 Socket Recv 方法

c - FreeTDS:如何设置运行存储过程的参数字符集

java - 使用 java nio 将字符串写入文件的最佳方法

java - 如何从 ArrayList 中添加和删除重复的对象?

java - 在 Mac OSX 上从 Java 启动 AppleScript 脚本

c++ - Windows 对其 Unicode 数据类型使用什么 unicode 编码(UTF-8、UTF-16 等)?

java - 无法打印俄语字符

python - 使用 python 以编程方式将 utf-8 字符(中文、阿拉伯语、日语等)记录插入到 GAE 数据存储中