3

在将 cobol 程序转换为 C# 时,我遇到了 COMP:

03  Var1                     PIC X(4).
03  Var2                     PIC X(3).
03  Var3                     PIC X(3).
03  Var4                     PIC X(4).
03  Var5                     PIC X(16).
03  Var6                     PIC X(4).
03  Var7                     PIC X(2).
03  Var8                     PIC X.
03  Var9                     PIC X(4).
03  Var10                    PIC X(16).
03  Var11                    PIC S9(7)V9(2) COMP.
03  Var12                    PIC S9(7)V9(2) COMP.
03  Var13                    PIC S9(7)V9(2) COMP.
03  Var14                    PIC S9(7)V9(2) COMP.
03  Var15                    PIC S9(7)V9(2) COMP.
03  Var16                    PIC S9(7)V9(2) COMP.
03  Var17                    PIC S9(7)V9(2) COMP.
03  Var18                    PIC S9(7)V9(2) COMP.
03  Var19                    PIC S9(7)V9(2) COMP.
03  Var20                    PIC S9(7)V9(2) COMP.
03  Var21                    PIC S9(7)V9(2) COMP.
03  Var22                    PIC S9(7)V9(2) COMP.
03  Var23                    PIC S9(7)V9(2) COMP.
03  Var24                    PIC S9(7)V9(2) COMP.

我花了几个小时研究 COMP。大多数搜索都会产生关于 COMP-3 的信息,或者提到 COMP 是二进制转换。但是,cobol 程序的 COMP 输出是非 COMP 字段,后跟(括号之间):

( F ” " )

而实际值都是 0.00,除了 var13 是 64.70

注意:这些是从 Notepad++ 复制的值。另外,请注意,我对 cobol 知之甚少。

如何从 COMP 转换为十进制?理想情况下,我也可以将十进制转换为 COMP,因为我需要将内容恢复为相同的格式。

我尝试使用以下方法以二进制形式读取数据:

public static void ReadBinaryFile(string directoryString)
    {
        using (BinaryReader reader = new BinaryReader(File.Open(directoryString, FileMode.Open)))
        {
            string myString = Encoding.ASCII.GetString(reader.ReadBytes(113));
            Console.WriteLine(myString);
        }
    }

编辑:在正确的轨道上

感谢@piet.t 和@jdweng 的帮助。

虽然此测试代码仍然存在问题,但这应该可以帮助我所在位置的任何人解决他们的问题:

public static void ReadBinaryFile(string directoryString)
    {
        using (BinaryReader reader = new BinaryReader(File.Open(directoryString, FileMode.Open)))
        {
            string asciiPortion = Encoding.ASCII.GetString(reader.ReadBytes(57)); // Read the non-comp values

            Console.Write(asciiPortion); // Test the ascii portion 

            Console.WriteLine("var11: " + reader.ReadInt32());
            Console.WriteLine("var12: " + reader.ReadInt32());
            Console.WriteLine("var13: " + reader.ReadInt32());
            Console.WriteLine("var14: " + reader.ReadInt32());
            Console.WriteLine("var15: " + reader.ReadInt32());
            Console.WriteLine("var16: " + reader.ReadInt32());
            Console.WriteLine("var17: " + reader.ReadInt32());
            Console.WriteLine("var18: " + reader.ReadInt32());
            Console.WriteLine("var19: " + reader.ReadInt32());
            Console.WriteLine("var20: " + reader.ReadInt32());
            Console.WriteLine("var21: " + reader.ReadInt32());
            Console.WriteLine("var22: " + reader.ReadInt32());
            Console.WriteLine("var23: " + reader.ReadInt32());
            Console.WriteLine("var24: " + reader.ReadInt32());
        }
    }

编辑2:试图找到问题

问题:每个值后面似乎都跟着一些垃圾值,这些值被打印为下一个 int32。

实际值:

var11 = var12 = 0.00
var13 = 58.90
var14 = 0.00
var15 = -0.14
var16 = 0.00
var17 = var18 = var19 = var20 = 0.00
var21 = var22 = var23 = var24 = 0.00

输出(带填充):

Var11:     0  HEX: 00000000  BIN: 00000000000000000000000000000000
Var12:     0  HEX: 00000000  BIN: 00000000000000000000000000000000
Var13:  5890  HEX: 00001702  BIN: 00000000000000000001011100000010
Var14:   368  HEX: 00000170  BIN: 00000000000000000000000101110000
Var15:   -14  HEX: FFFFFFF2  BIN: 11111111111111111111111111110010
Var16:    -1  HEX: FFFFFFFF  BIN: 11111111111111111111111111111111
Var17:     0  HEX: 00000000  BIN: 00000000000000000000000000000000
Var18:     0  HEX: 00000000  BIN: 00000000000000000000000000000000
Var19:     0  HEX: 00000000  BIN: 00000000000000000000000000000000
Var20:     0  HEX: 00000000  BIN: 00000000000000000000000000000000
Var21:     0  HEX: 00000000  BIN: 00000000000000000000000000000000
Var22:     0  HEX: 00000000  BIN: 00000000000000000000000000000000
Var23:     0  HEX: 00000000  BIN: 00000000000000000000000000000000
Var24:     0  HEX: 00000000  BIN: 00000000000000000000000000000000

记事本++(复制)表示:

          p  òÿÿÿÿÿÿÿ                                

Notepad++(视觉)表示:

[NUL][NUL][NUL][NUL][NUL][NUL][NUL][NUL][STX][ETB][NUL][NUL]p[SOH]
[NUL][NUL]òÿÿÿÿÿÿÿ[NUL][NUL][NUL][NUL][NUL][NUL][NUL][NUL][NUL][NUL]
[NUL][NUL][NUL][NUL][NUL][NUL][NUL][NUL][NUL][NUL][NUL][NUL][NUL]
[NUL][NUL][NUL][NUL][NUL][NUL][NUL][NUL][NUL][LF]

编辑3:解决方案!

@piet.t 一切正常。感谢您对我的第一个问题的有用回答!这个问题是 cobol 程序特有的。我被引导相信 Var14 始终为 0,但是:

Var14 = SomeCalculationIHadNoIdeaAbout(Var13, SomeOtherNumber);

我使用RecordEdit更轻松地调整数据(警告:程序在某些地方有点奇怪)并注意到“垃圾”值的奇怪趋势。

我的问题的真正解决方案是我几天前制作的第一个 EDIT 中的代码:/.

注意:我还必须使用一个换行符,我没有在该代码中添加它。为此,只需添加另一个reader.ReadBytes(1);.

注意 2:您可能需要查看EBDCDIC和/或Endianness,这可能会使您的解决方案比我的更困难。

4

1 回答 1

7

由于 COBOL 程序使用的是我认为 C# 不知道的定点变量,因此这里的事情会变得有点复杂。

对于转换,将每个PIC S9(7)V9(2) COMP-field 视为一个Int32(它应该是 BigEndian 格式)。但请注意,您不会得到实际值,而是value*100因为 COBOL 字段声明中的隐含小数点。

请注意,使用定点数据将允许精确计算带小数的值,而在 C# 中将其转换为浮点可能会导致舍入,因为二进制浮点并不总是准确地表示小数。

于 2017-06-13T06:19:54.490 回答