0

我正在尝试从一个应用程序获取数据并在处理数据后将其发送到另一个(大型机)。

假设我正在获取“这是来自另一个应用程序”的数据,处理与“此数据已处理”相同的处理状态。最终消息应结合使用编码(Cp1047)到大型机应用程序来读取与

0024这是来自另一个应用程序001A此数据已处理


0024 的十进制值为 36(消息长度 + 4 是十六进制值长度)
001A 的十进制值为 26(处理的消息长度 + 4)

我的应用程序在 Java8 上运行并使用 websphere MQ。我需要将数据发送到从 Mainframe MQ 接收数据的应用程序。WebSphere MQ 中的远程队列将消息放入大型机 MQ 的本地队列。我的代码如下,使用 Cp1047 转换数据和编码,

String incomingData = "This is from another application";
String processingData = "This data is processed" 
public String outGoingData(String incomingData, String processingData) {  
  StringBuilder strBuilder = new StringBuilder();
  return stringbuilder.append(new String(convertToEbcidie(incomingData, "Cp1047")))
  .append(incomingData)
  .append(new String(convertToEbcidie(processingData, "Cp1047")))
  .append(processing data).toString(); //playing this string to queue
}
private byte[] convertToEbcidic(String s) {
  String hexStr = StringUtils.leftPad(s.length+4, 8, "0");
  byte[] byteAry = new byte[hexStr.length()/2];
  for (int i = 0; i < hexStr.length(); i+=2) {
    byteAry[i/2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
                   + Character.digit(s.charAt(i+1), 16)); 
  }  return byteAry;
}

接收方应用程序(大型机)决定哪个是原始消息和基于处理状态的 4 个字符的十六进制值。他们能够阅读大部分信息,但不是全部。例如,长度 805 的十六进制值为 325,但在大型机 mq 条目中为 315。由于长度不匹配,它们无法处理。

另一个样本数据:- OO25这是来自源001A的原始数据,已成功处理


0025 是 org msg length(33) + 4 的十六进制值,001A 是处理后的 msg 长度 (22) + 4 的十六进制值。这里 4 是十六进制值的长度。
我是否缺少任何转换为​​ ebcidic 的逻辑?

4

3 回答 3

2

您发布的代码有很多错误,我不知道从哪里开始。

首先,StackOverflow 规则/策略是您应该将工作代码从编辑器或 IDE 复制并粘贴到 StackOverflow。显然,您没有这样做,而只是在 StackOverflow 编辑窗口中创建了新代码——这是错误的!!!

return stringbuilder.append(new String(convertToEbcidie(incomingData, "Cp1047")))
  .append(incomingData)
  .append(new String(convertToEbcidie(processingData, "Cp1047")))
  .append(processing data).toString();

(1) convertToEbcidic 方法采用 ONE 参数,而不是 2。您的括号错误。

(2) 方法名是convertToEbcidic而不是convertToEbcidie(最后一个字母是'c'而不是'e')

private byte[] convertToEbcidic(String s) {
  String hexStr = StringUtils.leftPad(s.length+4, 8, "0");
  byte[] byteAry = new byte[hexStr.length()/2];
  for (int i = 0; i < hexStr.length(); i+=2) {
    byteAry[i/2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
                   + Character.digit(s.charAt(i+1), 16)); 
  }  return byteAry;
}

(3) 我不知道您要做什么,但显然它没有做您认为的任何事情。您是否使用调试器单步执行代码?

(3A) s 变量的长度是一个方法而不是一个字段。它应该是“s.length()”而不是“s.length”。

(3B) StringUtils.leftPad 方法的第一个参数必须是 String 而不是 int。

(3C) hexStr 将为“00000036”(32 + 4)。hexStr 的长度为 8。

(3D) byteAry 的大小为 4!!!您如何将 36 个字符放入 4 个字节中?即 4 + 26 个字符“这是来自另一个应用程序”。

(3E) 你的循环在做什么?它运行了 4 次,我完全不知道你在想什么。

好的。现在到你的问题。

ANOTHER SAMPLE DATA :- OO25THIS IS ORIGINAL DATA FROM SOURCE001APROCESSED SUCCESSFULLY

好的。因此,基于该示例,在我看来布局如下:

{“字符数据1”长度的字符串表示,十六进制}{字符数据1}{“字符数据2”长度的字符串表示,十六进制}{字符数据2}

由于整个消息负载将是字符串,因此将字符串作为消息放在本地代码页(ASCII)中要好得多,将 MQMD 格式标记为字符串并让 MQ 进行转换。当大型机应用程序发出“MQGET with Convert”调用时,转换将完成。

这是您的问题的正确代码:

String incomingData = "This is from another application";
String processingData = "This data is processed";
StringBuilder sb = new StringBuilder();
MQQueueManager qMgr = null;
MQQueue outQ = null;

String inHexLen = Integer.toHexString(incomingData.length()+4).toUpperCase();
inHexLen = StringUtils.leftPad(inHexLen, 4, '0');
sb.append(inHexLen);
sb.append(incomingData);

String outHexLen = Integer.toHexString(processingData.length()+4).toUpperCase();
outHexLen = StringUtils.leftPad(outHexLen, 4, '0');
sb.append(outHexLen);
sb.append(processingData);

System.out.println("sb="+sb.toString());

try
{
   qMgr = new MQQueueManager("MQA1");

   outQ = qMgr.accessQueue("TEST.Q1",
                           CMQC.MQOO_OUTPUT + CMQC.MQOO_FAIL_IF_QUIESCING);

   MQMessage sendmsg = new MQMessage();
   sendmsg.format = CMQC.MQFMT_STRING;
   sendmsg.writeString(sb.toString());
   outQ.put(sendmsg, new MQPutMessageOptions());
}
catch (MQException e)
{
   e.printStackTrace();
}
catch (IOException e)
{
   e.printStackTrace();
}
finally
{
   try
   {
      if (outQ != null)
         outQ.close();
   }
   catch (MQException e)
   {
      e.printStackTrace();
   }
   try
   {
      if (qMgr != null)
         qMgr.disconnect();
   }
   catch (MQException e)
   {
      e.printStackTrace();
   }
}
于 2020-05-08T21:52:43.003 回答
1

似乎您尝试在消息中混合二进制数据和文本数据,并且您想要这样做的方式如下:

  • 您获取二进制字段并在客户端执行 EBCDIC->client-codepage 转换
  • 然后将其传递给 MQ,然后由 MQ 执行客户端代码页->EBCDIC 转换
  • 你希望你能回到你开始的地方

这可以工作,但在大多数情况下它不会,因为它需要:

  • 您的字符转换和 MQ 的字符转换使用相同的转换表
  • 这些转换表是双射的,即它们允许无损往返转换

特别是最后一点对于不可打印(甚至非映射)的字节值通常是不正确的。

因此,要么将数据作为不转换的二进制文件传输,要么作为带有转换的文本传输,但任何将两者混合的尝试都注定会失败。

于 2020-05-08T11:08:04.277 回答
0

在您发送到 zOS 的数据中,有一些 ASCII 字符和一些包含长度的字节

如果您将完整的字符串 - 组合文本字符通过代码转换,那么这就是完整字符串中的每个字节都会发生的情况 - 无论代码转换将尝试将每个字节从其 ASCII 值转换为等效的“EBCDIC”价值。

因此,在转换结束时,文本字符是正常的,因为它们是正常的可打印字符,但是包含长度的字节将被转换为一些 EBCDIC 字符并且不再可用于进行长度计算。

由于您在 zOS 上的应用似乎正在从 MQ 获取消息,因此您需要确保从 zOS 上的 MQ 获取消息,以便 MQ 不会为您进行转换。

然后,您需要解析消息,而不是在一次操作中将整个消息转换为 EBCDIC。

将消息的前两个字节转换为具有第一个文本长度的变量(没有转换),谷歌如何编写 Java 代码将其转换为 java int,然后使用该值将那些 N 个字节取出MQ 字符串,然后在这些字节上转换为 EBCDIC,

然后在第一个字符串结束后从 MQ 消息中获取两个字节,并重复上述过程。

于 2020-05-11T08:09:00.400 回答