Распаковка упакованных десятичных знаков EBCDIC (COMP-3) в преобразовании ASCII - PullRequest
7 голосов
/ 01 марта 2010

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

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

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

1 Ответ

3 голосов
/ 05 марта 2010

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

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

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

(Возможность # 2) Если предположить, что это не так просто (например, файл вводится для других программ или не может изменить код), вы можете написать в системе другую программу на языке 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, если это $$$. Float & Double вызовет у вас горе! Если вы не обрабатываете его, лучше использовать даже строку.

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

Мир, -Аль

...