Распаковка упакованных десятичных чисел EBCDIC (АККОМПАНИРУЮТ 3) в преобразовании ASCII

Я использую реализацию EBCDIC Jon Skeet в.NET для чтения файла VSAM, загруженного в режиме двоичного счета FTP от мейнфреймовой системы. Это работает очень хорошо на чтение/запись в этом кодировании, но это не имеет ничего для чтения значений упакованного десятичного числа. Мой файл содержит их, и я должен распаковать их (за счет большего количества байтов, очевидно).

Как я могу сделать это?

Мои поля определяются как PIC S9(7)V99 COMP-3.

7
задан Josh Stodola 1 March 2010 в 14:26
поделиться

1 ответ

Ах, BCD. Сигнал, если вы использовали его в сборке 6502.

Конечно, лучше всего позволить COBOL MOVE сделать всю работу за вас! Одна из этих возможностей может помочь.

(Возможность №1) Предполагая, что у вас есть доступ к мэйнфрейму и исходному коду, а выходной файл предназначен ТОЛЬКО для вашего использования, измените программу так, чтобы она просто ПЕРЕМЕЩАЕТ значение в простой распакованный PIC S9 (7) V99 .

(Возможность №2) Предполагая, что это не так просто (например, файл вводится для других pgms или не может изменить код), вы можете написать другую программу COBOL в системе, которая читает этот файл и записывает другой. Вырежьте и вставьте макет записи файла с BCD в новую программу для входных и выходных файлов. Измените выходную версию, чтобы она не была упакована. Прочтите запись, выполните «соответствующий ход» для передачи данных и напишите до eof. Затем передайте тот файл.

(Возможность №3) Если вы не можете дотронуться до мэйнфрейма, обратите внимание на описание в статье, на которую вы указали ссылку в своем комментарии. BCD относительно прост. Это могло быть таким же простым (vb.net):

Private Function FromBCD(ByVal BCD As String, ByVal intsz As Integer, ByVal decsz As Integer) As Decimal
    Dim PicLen As Integer = intsz + decsz
    Dim result As Decimal = 0
    Dim val As Integer = Asc(Mid(BCD, 1, 1))
    Do While PicLen > 0
        result *= 10D
        result += val \ 16
        PicLen -= 1
        If PicLen > 0 Then
            result *= 10D
            result += val Mod 16
            PicLen -= 1
            BCD = Mid(BCD, 2)
        End If
        val = Asc(Mid(BCD, 1, 1))
    Loop
    If val Mod 16 = &HD& Then
        result = -result
    End If
    Return result / CDec(10 ^ decsz)
End Function

Я тестировал его с несколькими вариантами этого вызова:

MsgBox(FromBCD("@" & Chr(13 + 16), 2, 1))

Например, -40,1. Но всего несколько. Так что это все еще может быть неправильным.

Итак, если ваш comp-3 запускается, скажем, с 10 байта макета входной записи, это решит эту проблему:

dim valu as Decimal = FromBCD(Mid(InputLine,10,5), 7,2))

Обратите внимание на формулы из статьи о преобразовании данных для # байтов для отправки, и # 9 перед и после V.

Сохраните результат в десятичном формате, чтобы избежать ошибок округления. Esp, если это $$$. Поплавок и двойник вызовут у вас горе! Если вы его не обрабатываете, лучше даже строка.

конечно, могло быть сложнее.Там, где я работаю, у мэйнфрейма 9 бит на байт. Серьезный. Вот что делает первые две возможности такими важными. Конечно, что действительно делает их лучше, так это тот факт, что вы можете быть программистом только на ПК, и это отличный повод, чтобы заставить программиста мэйнфреймов сделать эту работу за вас! Если вам так повезло, что у вас есть такая возможность ...

Мир, - Ал

3
ответ дан 7 December 2019 в 16:41
поделиться
Другие вопросы по тегам:

Похожие вопросы: