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.

+3


source to share


1 answer


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.

+7


source







All Articles