Распаковка десятичных дробей, упакованных в формате EBCDIC (COMP-3), в преобразовании ASCII

StackOverflow https://stackoverflow.com/questions/2356424

Вопрос

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

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

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

Это было полезно?

Решение

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

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

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

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

(Возможность № 3) Если вы не можете прикоснуться к мэйнфрейму, обратите внимание на описание в статье, на которую вы дали ссылку в своем комментарии.BCD относительно прост.IT мог бы будь таким же простым, как это (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.

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

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

Мира, -Ал

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top