在ASCII转换中解压缩EBCDIC压缩十进制(COMP-3)

Jos*_*ola 7 .net c# ascii ebcdic comp-3

在.NET中使用Jon Skeet的EBCDIC实现来读取从大型机系统使用FTP以二进制模式下载的VSAM文件.它在这种编码中非常适合读/写,但它没有任何东西可以读取压缩十进制值.我的文件包含这些,我需要解压缩它们(显然是以更多的字节为代价).

我怎样才能做到这一点?

我的字段定义为 PIC S9(7)V99 COMP-3.

Fas*_*tAl 4

啊,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
Run Code Online (Sandbox Code Playgroud)

我用这个调用的一些变体测试了它:

MsgBox(FromBCD("@" & Chr(13 + 16), 2, 1))
Run Code Online (Sandbox Code Playgroud)

例如,是-40.1。但只有几个。所以它可能仍然是错误的。

因此,如果您的 comp-3 从输入记录布局的字节 10 开始,这将解决该问题:

dim valu as Decimal = FromBCD(Mid(InputLine,10,5), 7,2))
Run Code Online (Sandbox Code Playgroud)

注意数据转换文章中关于要发送的字节数以及 V 前后的 9 数的公式。

将结果存储为 Decimal 以避免舍入错误。特别是如果它是$$$。浮动和双倍会让你悲伤!如果您不处理它,即使是字符串也更好。

当然,这可能会更难。我工作的地方,大型机每字节 9 位。严肃的。这就是前两种可能性如此突出的原因。当然,真正让它们变得更好的是,您可能只是一名 PC 程序员,这是让大型机程序员为您完成工作的一个很好的借口!如果你很幸运有这样的选择......

和平,-阿尔