Проблема с форматом чисел COBOL COMP-3

У меня есть дамп "ленточного формата" кобола, в котором есть смесь текстовых и числовых полей. Я читаю файл на C # как двоичный массив (массив байтов). У меня есть тетрадь, и форматы отлично выстраиваются в текстовых полях. Также есть ряд полей COMP-3. Данные в этих полях не соответствуют формату BCD. Я знаю, какими должны быть данные, и у меня есть необработанные байты COMP-3. Сначала я попытался преобразовать в EBCDIC, что не дало лучших результатов. Есть ли какие-либо мысли о том, как номер COMP-3 может быть иначе сохранен внутри? Ниже приведены три примера PIC, необработанные данные и ожидаемое число. Я знаю, что у меня правильные позиции полей, потому что по обе стороны от чисел есть альфа-данные, и все они выровнены правильно.

Первый пример: PIC поля - 9 (9) COMP-3. Данные имеют 5 байтов, шестнадцатеричные значения - 02 01 20 91 22. В результате должны быть данные в виде даты (00CCYYMMDD). Эта конкретная дата должна быть 3-17-14.

Второй пример: PIC поля - S9 (3) COMP-3. Имеются 2 байта данных, шестнадцатеричные значения - 0A 14 Результирующее значение должно быть между 900 и 999 Насколько я понимаю, «S» означает, что последний полубайт должен быть 0xC или 0xD для обозначения + или -

Третий пример: PIC поля - S9 (15) V99 COMP-3. В данных 9 байтов, шестнадцатеричные значения - 00 00 00 00 00 00 01 80 0C. В результате должно получиться значение 12.00.

Хорошо, спасибо людям, которые откликнулись и указали мне правильное направление. Это действительно проблема представления ASCII / EBCDIC. BCD хранится в EBCDIC. Использование таблицы преобразования ASCII в EBCDIC дает правильно отформатированные цифры BCD:

Я использовал эту ссылку для сопоставления данных: http://shop.alterlinks.com/ascii-table/ascii-ebcdic-us.php

Мои данные: 0A 14 Преобразовано: 25 3C (оказалось, что 253 - допустимое значение, спецификация была неправильной) C = +, все хорошо

Мои данные: 01 80 0C (без начальных нулей) Преобразовано: 01 20 0C 12.00 C = +, подразумевается 2 цифры в формате, все в порядке

Мои данные: 02 01 20 91 22 Преобразовано: 02 01 40 31 7F 2014/03/17 (F - неиспользованный полубайт), все хорошо


person Shaun Neal    schedule 02.04.2014    source источник


Ответы (5)


Не существует такой вещи, как COBOL "tape format", хотя эта фраза может что-то значить для человека, который предоставил вам данные.

Ключ к разгадке вашей проблемы в том, что вы можете читать текст. Подключите это к тегу EBCDIC и вашей ссылке на C #.

Итак, вы читаете данные, которые изначально исходят от мэйнфрейма, скорее всего, от мэйнфрейма IBM, который использует EBCDIC вместо ASCII.

COBOL не имеет встроенной поддержки BCD.

Какая-то добрая душа сделала для вас "преобразование" данных из EBCDIC в ASCII. Иначе вы даже не узнали бы «текст».

К сожалению, это означает, что для любых двоичных или упакованных десятичных или полей с плавающей запятой (вы не увидите большую часть последних, но это COMP-1 / COMP-2), это то, что "convert" означает "потенциально зашифрованные", потому что покрытие принимает отдельные байты с простыми байтовыми значениями, тогда как все эти поля имеют обычное кодирование, либо через несколько байтов, либо через значения не-EBCDIC, либо и то, и другое.

Итак: КОМП-3 ПИК 9 (9). Как вы говорите, пять байт. Он беззнаковый, поэтому крайний правый полубайт будет F (все биты включены). Вы немного теряете свои позиции из-за того, что позиция знака занята, даже для поля без знака.

На мэйнфрейме он содержит значение X'020140317F'. Только это поле целиком может иметь какое-либо значение в отношении его значения. Однако преобразование EBCDIC в ASCII сделало его X'0201209122 '.

Как?

Найдите значение EBCDIC X'02' и X'01'. Они не меняются. Найдите значение X'40', упс, это пробел, измените его на ASCII X'20'. Найдите значение X'31'. На самом деле ничего особенного там нет, и он преобразован во что-то более высокое, чем X'7F', но если вы посмотрите на используемую таблицу перевода, я думаю, вы поймете, почему это происходит. X'7F' - это двойные кавычки, поэтому заменяется на X'22'.

Другие ценности, которые вы показываете, страдают той же проблемой.

Вы должны всегда получать данные с мэйнфрейма только в символьном формате. Здесь есть много ответов на этот вопрос, вы должны посмотреть на related справа.

Взгляните на этот недавний вопрос: Преобразование COMP и COMP-3 Packed Decimal в читаемое значение с помощью C

person Bill Woodger    schedule 02.04.2014
comment
Итак, прежде всего спасибо всем за кропотливую работу и подробные ответы. Я попробовал выполнить перевод кодовой страницы EBCDIC, как вручную, так и с помощью функции перевода C #, и столкнулся с аналогичными проблемами, как указано выше (например, отсутствие отображения символов). К сожалению, поставщик данных (в данном случае First Data) не будет изменять предоставленный формат. Формат ленты относится к названию документа, на случай, если кто-то из сотрудников FDR может знать об этом. Это формат «20», в котором представлены данные о расходах по картам для эмитентов кредитов. - person Shaun Neal; 02.04.2014
comment
К сожалению, спецификация является конфиденциальной и не может быть размещена в Интернете. Однако он не содержит никаких подсказок о том, в какой кодовой странице EBCDIC он хранится. Я послал в них еще один вызов, чтобы посмотреть, смогу ли я это выяснить, но похоже, что это проблема перевода EBCDIC на данный момент. - person Shaun Neal; 02.04.2014
comment
В стороне - это стандартизированный (хотя и конфиденциальный) формат, используемый в отрасли, поэтому где-то есть волшебный соус, который преобразует эти зашифрованные символы. Другие люди успешно загрузили этот файл, и этот файл создается в соответствии с тщательно документированной спецификацией, которая существует буквально десятилетиями. - person Shaun Neal; 02.04.2014

Хорошо, давайте посмотрим на ваш первый пример. Учитывая формат и значение, исходный BCD-контент должен был быть чем-то вроде

02 01 40 31 7F

При преобразовании этого из EBCDIC в ASCII мы сталкиваемся с проблемами с первым, вторым и четвертым байтами, потому что они являются управляющими символами, поэтому здесь нам понадобятся некоторые дополнительные сведения о том, как работал конвертер ASCII-> EBCDIC. Глядя на два оставшихся байта, они будут изменены

EBCDIC     ASCII     CHARACTER
40      -> 20        (blank)
7F      -> 22         "

Предполагая, что первые два байта остаются неизменными, а третий преобразуется как 31->91, мы получаем

02 01 20 91 22

что у вас есть. Похоже, что произошло какое-то преобразование EBCDIC-> ASCII. Если это так, возможно, вы не сможете восстановить данные, поскольку преобразование не может быть однозначным и, следовательно, необратимым.

Рассматривая второй пример и используя

EBCDIC     ASCII     CHARACTER
25      -> 0A        (LF)
3C      -> 14        (DC4)

вы бы начали с 25 3C, который соответствовал бы формату, но не указанному вами диапазону.

В третьем примере исходный 01 20 0C может быть преобразован в 01 80 0C, поскольку 20 также является управляющим символом EBCDIC без прямого эквивалента ASCII.

Но, учитывая все другие примеры, я предполагаю, что существует некоторая проблема с преобразованием кодовых страниц. Если вы использовали какой-то перенос файлов для перемещения данных из (предполагаемого) мэйнфрейма, убедитесь, что он установлен в двоичный режим и не выполняет никакого преобразования символов, прежде чем разбивать файл на поля и знать, что должно быть символом. и что "нет.

РЕДАКТИРОВАТЬ: вы можете найти список из нескольких кодовых страниц на основе EBCDIC и ASCII здесь или посмотрите здесь за то же, что и один pdf.

person piet.t    schedule 02.04.2014
comment
Как я уже сказал: X'91 '- это всего лишь предположение - поскольку X'31' абсолютно не имеет значения в EBCDIC, он может быть сопоставлен с чем угодно. Глядя на наши таблицы трансляции эмуляций терминала, они будут сопоставлены с X'2D ', как и большинство других значений в этой области, но могут произойти всевозможные странные вещи ... - person piet.t; 02.04.2014
comment
Что-то, что может помочь сообществу (и мне, ха-ха), - это ссылка или репост доступных кодовых страниц EBCDIC и их сопоставлений. Я нашел несколько обрывков в Интернете, но ничего определенного. Есть большая вероятность, что это действительно мэйнфрейм IBM. Некоторое время назад я выполнял некоторую контрактную работу для поставщика (First Data), и все это была IBM. - person Shaun Neal; 02.04.2014

Я подхожу к этому немного поздно, но у меня есть пара предложений, которые могут облегчить вам жизнь ...

Во-первых, посмотрите, сможете ли вы заставить ваши компоненты мэйнфрейма преобразовывать все несимвольные (то есть двоичные числовые и упакованные десятичные) данные в формат отображения (например, PIC X), прежде чем загружать его. Тогда вам нужно будет иметь дело только с «печатаемым» диапазоном числовых символов, представляющих от 0 до 9. Преобразование кодовой страницы только для печатных символов является довольно стандартным и, как правило, не так сильно ошибается. Переформатирование данных в тетрадке - не сложная перспектива для любого, кто разбирается в среде мэйнфреймов. К сожалению, иногда вы получаете «обходной путь», и заявляют, что это чрезвычайно дорого или требует специального программного обеспечения, или любого из сотни других поддельных оправданий.

Если вы получили «обходной путь», то лучше всего будет загрузить файл в двоичном формате и выполнить собственное преобразование кодовой страницы для символьных данных (довольно просто). Затем займитесь двоичными данными на основе определений из вашей тетради. С помощью нескольких Google вы сможете найти достаточно информации для преобразования данных PACKED-DECIMAL (COMP-3) во все, что вам нужно.

Вот пара ссылок, с которых можно начать:

Числовые форматы данных

Packed Decimal

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

person NealB    schedule 02.04.2014

Хорошо, спасибо обоим людям, которые ответили и указали мне правильное направление. Это действительно проблема представления ASCII / EBCDIC. BCD хранится в EBCDIC. Использование таблицы преобразования ASCII в EBCDIC дает правильно отформатированные цифры BCD:

Я использовал эту ссылку для сопоставления данных: http://shop.alterlinks.com/ascii-table/ascii-ebcdic-us.php

My data:    0A 14
Converted:  25 3C  (turns out that 253 is a valid value, spec was wrong) C = +, all good

My data:    01 80 0C  (excluding leading zeros)
Converted:  01 20 0C  12.00  C = +, implied 2 digits in format, all good

My data:    02 01 20 91 22
Converted:  02 01 40 31 7F     2014/03/17  (F is unused nibble), all good

Еще раз спасибо за два приведенных выше ответа, которые привели меня в правильном направлении.

person Shaun Neal    schedule 02.04.2014
comment
Как отмечалось выше, решение заключалось в том, чтобы преобразовать поля EBCDIC обратно в ASCII, используя перевод кодовой страницы по ссылке выше, а затем применить стандартную логику сопоставления comp-3. Первые два предложения привели меня в правильном направлении, но у обоих были небольшие проблемы с переводами, которые делали их технически некорректными, поскольку они пришли к выводу, что преобразование EBCDIC в ASCII по-прежнему приводит к неверным значениям, что на самом деле неверно. - person Shaun Neal; 26.04.2014

Вы можете избежать вышеуказанных проблем, преобразовав данные в современный метод передачи данных: XML.

person JackCColeman    schedule 24.04.2014
comment
К сожалению, поставщик управляет бизнесом и, по сути, большей частью отрасли, и его не волнуют переводы. Суть вопроса и упражнения заключались в том, чтобы найти решение для чисел Comp-3, упакованных в EBCDIC, что я в конечном итоге и сделал. - person Shaun Neal; 26.04.2014