How can I convert the output of a Cobol COMP field to a readable decimal in C #?
When converting a cobol program to C #, I ran into 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.
I spent several hours researching COMP. Most queries give something about COMP-3 or mention that COMP is a binary conversion. However, COMP COMP COMPOM are non-COMP fields followed (between parentheses):
( F " " )
whereas the actual values are 0.00 except var13 is 64.70
NOTE: these are values copied from Notepad ++. Also, please note that I don't know much about cobol.
How to convert from COMP to decimal? Ideally, I could also convert the decimal code to COMP, since I need to return everything to the same format.
I have tried reading data in binary with
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);
}
}
EDIT: On the right track
Thanks @ piet.t and @jdweng for the help.
While there is still a problem with this test code, this should help anyone in my position with their solution:
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());
}
}
EDIT 2: Trying to find the problem
Problem: Some amount of garbage appears behind each value, which is printed as the next int32.
Actual values:
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
Output (with addition):
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 ++ (copied) View:
p òÿÿÿÿÿÿÿ
Notepad ++ (visual) presentation:
[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]
EDIT 3: Solution!
@ piet.t is ok. Thanks for the helpful answer to my first question! The problem was something specific to the cobol program. I was convinced that Var14 is always 0, but:
Var14 = SomeCalculationIHadNoIdeaAbout(Var13, SomeOtherNumber);
I used RecordEdit to tweak the data easier (warning: the program is a little strange) and noticed a strange trend in the garbage values.
The real solution to my problem is the code in the first EDIT I made a few days ago: /.
NOTE. I also had to use the line symbol, which I did not enter in this code. To do this, just add another one reader.ReadBytes(1);
.
NOTE 2 You may need to learn EBDCDIC and / or Endianness , which can lead to a solution that is slightly more complicated than mine.
source to share
This is going to be a little tricky here, as COBOL-Program uses fixed point variables, which I think C # doesn't know about.
To convert, treat each PIC S9(7)V9(2) COMP
-field as Int32
(it must be BigEndian format). But note that you won't get the actual value, but value*100
because of the implicit decimal point in the COBOL field declaration.
Note that using fixed point data will allow decimal values to be computed accurately when converting it to floating point in C #, can lead to rounding, since binary floating points cannot always accurately represent decimal numbers.
source to share