JAVA в EBCIDI C Конвертация не происходит - PullRequest
0 голосов
/ 07 мая 2020

Я пытаюсь получить данные из одного приложения и отправить их в другое (мэйнфрейм) после обработки данных. Предположим, я получаю данные как «Это из другого приложения», обработанные так же и статус обработки, как «Эти данные обрабатываются». Окончательное сообщение должно представлять собой комбинацию того и другого с использованием кодировки (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 - это шестнадцатеричное значение длины организационного сообщения (33) + 4, а 001A - шестнадцатеричное число длины обработанного сообщения (22) + 4. Здесь 4 - длина шестнадцатеричного десятичного значения. Мне не хватает logi c для преобразования в ebcidi c?

Ответы [ 3 ]

2 голосов
/ 09 мая 2020

В опубликованном вами коде так много неправильного, что я не знаю, с чего начать.

Прежде всего, правила / политика 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) Метод convertToEbcidi c принимает ОДИН параметр, а не 2. Вы ошиблись брекетингом.

(2) Имя метода - convertToEbcidi c, а не convertToEbcid ie (последняя буква - '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.

(3 C) hexStr будет «00000036» (32 + 4). hexStr имеет длину 8.

(3D) byteAry будет иметь размер 4 !!! Как вы думаете уместить 36 символов в 4 байта? т.е. 4 + 26 символов «Это из другого приложения».

(3E) Что делает ваш l oop ?? Он запускается 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();
   }
}
1 голос
/ 08 мая 2020

Похоже, вы пытаетесь смешать двоичные и текстовые данные в своем сообщении, и способ, которым вы хотите это сделать, выглядит следующим образом:

  • Вы берете двоичные поля и выполняете EBCDI C -> преобразование клиентской кодовой страницы на стороне клиента
  • Затем вы передаете его в MQ, который затем выполняет преобразование клиентской кодовой страницы-> EBCDI C преобразование
  • Вы надеетесь, что вы будете туда, откуда вы начали

Это может сработать, но в большинстве случаев это не так, потому что для этого требуется, чтобы:

  • преобразование вашего символа и преобразование символа MQ использовали идентичное преобразование -tables
  • эти таблицы преобразования являются биективными, т. е. они допускают двустороннее преобразование без потерь

Особенно последний пункт обычно неверен для непечатаемых (или даже не отображаемых) ) byte-values.

Таким образом, передавайте данные либо как двоичные без преобразования, либо как текст с преобразованием, но любая попытка смешать и то и другое обречена на провал.

0 голосов
/ 11 мая 2020

В данных, которые вы отправляете в zOS, есть некоторые символы, которые являются ASCII, и некоторые байты, которые содержат длину

Если вы поместите эту полную строку - объединенных текстовых символов с помощью преобразования кода, тогда это будет что происходит с каждым байтом в полной строке - независимо от того, что делает преобразование кода, будет пытаться преобразовать каждый байт из его значения ASCII в эквивалентное значение «EBCDI C».

Таким образом, в конце преобразования текстовые символы в порядке, поскольку они являются обычными печатаемыми символами, но байты, содержащие длину, будут преобразованы в некоторые символы EBCDI C и больше не могут использоваться для вычисления длины.

Поскольку кажется, что ваше приложение на zOS ПОЛУЧАЕТ сообщение от MQ, вам необходимо убедиться, что вы ПОЛУЧИЛИ сообщение от MQ на zOS, чтобы MQ НЕ выполнял преобразование за вас.

Тогда вместо преобразования всего сообщения в EBCDI C за одну операцию вам нужно проанализировать сообщение.

Получить первые два байта сообщения в переменную (без преобразования), которая имеет длина первого текста, погуглите, как написать код Java, чтобы преобразовать его в java int, затем используйте это значение, чтобы получить эти N байтов из строки MQ, а затем выполнить преобразование в EBCDI C на этих байтах

затем получите два байта из сообщения MQ после конца этой 1-й строки и повторите описанный выше процесс.

...