Я использую реализацию EBCDIC Jon Skeet в.NET для чтения файла VSAM, загруженного в режиме двоичного счета FTP от мейнфреймовой системы. Это работает очень хорошо на чтение/запись в этом кодировании, но это не имеет ничего для чтения значений упакованного десятичного числа. Мой файл содержит их, и я должен распаковать их (за счет большего количества байтов, очевидно).
Как я могу сделать это?
Мои поля определяются как PIC S9(7)V99 COMP-3.
Ах, 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 бит на байт. Серьезный. Вот что делает первые две возможности такими важными. Конечно, что действительно делает их лучше, так это тот факт, что вы можете быть программистом только на ПК, и это отличный повод, чтобы заставить программиста мэйнфреймов сделать эту работу за вас! Если вам так повезло, что у вас есть такая возможность ...
Мир, - Ал