首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在ASCII转换中解包EBCDIC压缩小数(COMP-3)

在ASCII转换中解包EBCDIC压缩小数(COMP-3)
EN

Stack Overflow用户
提问于 2010-03-01 22:27:00
回答 2查看 13.8K关注 0票数 7

我正在使用Jon Skeet's EBCDIC implementation in .NET从一个大型机系统读取一个用FTP以二进制模式下载的VSAM文件。在这种编码中,它可以很好地进行读/写,但它没有任何东西可以读取压缩十进制值。我的文件包含这些,我需要解压它们(显然是以更多的字节为代价)。

我该怎么做呢?

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

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2010-03-06 04:20:32

啊,BCD。如果您在6502组件中使用它,请按喇叭。

当然,最好的办法是让COBOL MOVE为您完成这项工作!这些可能性中的一个可能会有所帮助。

(可能性#1)假设您确实可以访问大型机和源代码,并且输出文件仅供您使用,请修改程序,使其仅将值移动到一个未打包的PIC S9(7)V99。

(可能性#2)假设这不是那么简单(例如,文件是为其他pgms输入的,或者不能更改代码),您可以在系统上编写另一个COBOL程序来读取该文件并写入另一个文件。使用BCD将文件记录布局剪切并粘贴到用于输入和输出文件的新程序中。将输出版本修改为非压缩版本。读取一条记录,执行“相应的移动”来传输数据,然后写入,直到eof。然后转移那个文件。

(可能性#3)如果你不能触摸大型机,请记下你评论中链接的文章中的描述。BCD相对简单。它可以像下面这样简单(vb.net):

代码语言:javascript
复制
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

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

代码语言:javascript
复制
MsgBox(FromBCD("@" & Chr(13 + 16), 2, 1))

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

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

代码语言:javascript
复制
dim valu as Decimal = FromBCD(Mid(InputLine,10,5), 7,2))

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

将结果存储在Decimal中,以避免舍入错误。如果是$$$,则为Esp。Float & Double会给你带来悲哀!如果您不处理它,那么即使是字符串也更好。

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

和平,-Al

票数 4
EN

Stack Overflow用户

发布于 2021-01-22 01:11:25

我使用此扩展方法进行压缩十进制(BCD)转换:

代码语言:javascript
复制
    /// <summary>
    /// computes the actual decimal value from an IBM "Packed Decimal" 9(x)v99 (COBOL COMP-3) format
    /// </summary>
    /// <param name="value">byte[]</param>
    /// <param name="precision">byte; decimal places, default 2</param>
    /// <returns>decimal</returns>
    public static decimal FromPackedDecimal(this byte[] value, byte precision = 2)
    {
        if (value.Length < 1)
        {
            throw new System.InvalidOperationException("Cannot unpack empty bytes.");
        }
        double power = System.Math.Pow(10, precision);
        if (power > long.MaxValue)
        {
            throw new System.InvalidOperationException(
                $"Precision too large for valid calculation: {precision}");
        }
        string hex = System.BitConverter.ToString(value).Replace("-", "");
        var bytes = Enumerable.Range(0, hex.Length)
                 .Select(x => System.Convert.ToByte($"0{hex.Substring(x, 1)}", 16))
                 .ToList();
        long place = 1;
        decimal ret = 0;
        for (int i = bytes.Count - 2; i > -1; i--)
        {
            ret += (bytes[i] * place);
            place *= 10;
        }
        ret /= (long)power;
        return (bytes.Last() & (1 << 7)) != 0 ? ret * -1 : ret;
    }
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2356424

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档