如何在 C# 中将 Cobol COMP 字段输出转换为可读十进制?
How can I convert a Cobol COMP field output to readable decimal in C#?
在将一个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);
我使用 来更轻松地调整数据(警告:该程序在某些地方有点奇怪)并注意到 "garbage" 值出现奇怪的趋势。
我问题的真正解决方案是我几天前制作的第一个 EDIT 中的代码:/.
注意:我还必须使用一个换行符,我没有在该代码中输入它。为此,只需添加另一个 reader.ReadBytes(1);
.
注意 2:您可能需要查看 EBDCDIC and/or Endianness,这可能会使您的解决方案比我的更难一些。
这里的事情会变得有点复杂,因为 COBOL 程序正在使用我认为 C# 不知道的定点变量。
对于转换,将每个 PIC S9(7)V9(2) COMP
字段视为一个 Int32
(它应该是 BigEndian 格式)。但请注意,由于 COBOL 字段声明中的隐式小数点,您不会获得实际值,而是 value*100
。
请注意,使用定点数据可以精确计算带小数的值,而在 C# 中将其转换为浮点数可能会导致四舍五入,因为二进制浮点数不能始终准确表示小数。
在将一个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);
我使用
我问题的真正解决方案是我几天前制作的第一个 EDIT 中的代码:/.
注意:我还必须使用一个换行符,我没有在该代码中输入它。为此,只需添加另一个 reader.ReadBytes(1);
.
注意 2:您可能需要查看 EBDCDIC and/or Endianness,这可能会使您的解决方案比我的更难一些。
这里的事情会变得有点复杂,因为 COBOL 程序正在使用我认为 C# 不知道的定点变量。
对于转换,将每个 PIC S9(7)V9(2) COMP
字段视为一个 Int32
(它应该是 BigEndian 格式)。但请注意,由于 COBOL 字段声明中的隐式小数点,您不会获得实际值,而是 value*100
。
请注意,使用定点数据可以精确计算带小数的值,而在 C# 中将其转换为浮点数可能会导致四舍五入,因为二进制浮点数不能始终准确表示小数。