【发布时间】:2017-06-12 16:37:25
【问题描述】:
在将 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
Notepad++(复制)表示:
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,这可能会使您的解决方案比我的更困难。
【问题讨论】:
-
使用 BitConverter。可能需要使用 Big Endian 或 Little Endian,因为 IBM 通常从 microsoft 倒退。它看起来像 Cobol 使用标准 4/8 字节 IEEE 格式的浮点数。请参阅 IBM:ibm.com/support/knowledgecenter/en/SS6SG3_3.4.0/…
-
我假设你有 4 个字节,这是你的二进制文件。由于它在文件中,因此必须将 ascii 解析为字节。然后使用 BitConverter 将字节转换为浮点/双精度。
-
@jdweng 请注意,
COMP-fields 始终是定点/整数,float/double 将是COMP-1或COMP-2。 -
Comp-3 真的很老了。看起来 BCD (Binary Coded Decimal).PACKED-DECIMAL 和 COMP-3 是同义词。您在 PICTURE 描述中编码的每两个十进制数字,压缩十进制项目占用 1 个字节的存储空间,除了最右边的字节仅包含一个数字和符号。当您在 PICTURE 描述中编码奇数位数时,这种格式最有效,因此最左边的字节被完全使用。压缩十进制项目被处理为用于算术目的的定点数。见维基:en.wikipedia.org/wiki/Binary-coded_decimal
-
@jdweng 我不相信 2014 年之前的 COBOL 标准规定了浮点数的内部格式;这取决于编译器编写者。 IBM 大型机 COBOL 编译器仍然使用十六进制浮点(HFP,原始 System/360 格式),即使是 6.1。保留字
STANDARD-BINARY(IEEE 二进制浮点 (BFP) 和STANDARD-DECIMAL(十进制浮点 (DFP),IEEE-754/2008)在 2002 标准的 2010 修订版中添加,但 IBM 尚未为大型机编译器。他们这样做很容易,因为现在都使用相同的底层代码生成器。
标签: c# cobol packed-decimal