Unpacking EBCDIC Packed Decimals (COMP-3) in ASCII Conversion

I am using the Jon Skeet EBCDIC version in .NET to read a VSAM file downloaded in binary mode from FTP from the mainframe system. It works great for reading / writing in this encoding, but it has nothing to read packed decimal values. My file contains them, and I need to unpack them (due to more bytes).

How can i do this?

My fields are defined as PIC S9(7)V99 COMP-3.

+7
c # ascii ebcdic comp-3
source share
1 answer

Ahh, BCD. Honk, if you used it in build 6502.

Of course, it's best to let COBOL MOVE do the work for you! One of these features may help.

(Possibility # 1) Assuming that you have access to the mainframe and source code, and the output file is ONLY for your use, change the program so that it simply MOVES the value equal to the idle PIC S9 (7) V99,

(Possibility No. 2) Assuming that it is not so simple (for example, a file is entered for other pgms or cannot change the code), you can write another COBOL program on a system that reads this file and writes another. Cut and paste the layout for recording a file with BCD into a new program for input and output of files. Change the output version that will not be packaged. Read the entry, do the “move appropriate” to transfer data and write until it is. Then transfer this file.

(Opportunity No. 3) If you cannot touch the mainframe, pay attention to the description in the article that you indicated in your comment. BCD is relatively simple. It could be as simple as this (vb.net):

 Private Function FromBCD(ByVal BCD As String, ByVal intsz As Integer, ByVal decsz As Integer) As Decimal Dim PicLen As Integer = intsz + decsz Dim result As Decimal = 0 Dim val As Integer = Asc(Mid(BCD, 1, 1)) Do While PicLen > 0 result *= 10D result += val \ 16 PicLen -= 1 If PicLen > 0 Then result *= 10D result += val Mod 16 PicLen -= 1 BCD = Mid(BCD, 2) End If val = Asc(Mid(BCD, 1, 1)) Loop If val Mod 16 = &HD& Then result = -result End If Return result / CDec(10 ^ decsz) End Function 

I tested it with several variations of this call:

 MsgBox(FromBCD("@" & Chr(13 + 16), 2, 1)) 

For example, is -40.1. But only a few. So everything may be wrong.

So, if your comp-3 runs, say, in byte 10 of the layout of the input record, this will solve it:

 dim valu as Decimal = FromBCD(Mid(InputLine,10,5), 7,2)) 

Noting the formulas from the data conversion article for # bytes to send and # of 9 before and after V.

Save the result in decimal to avoid rounding errors. Esp if it is $$$. Float and Double KILL you grief! If you do not process it, even a string is better.

Of course, this can be trickier. Where I work, the mainframe is 9 bits per byte. Serious. This is what makes the first 2 features so noticeable. Of course, what really makes them better is that you can be a PC programmer, and this is a great reason to get a mainframe programmer to do the job for you! If you are so lucky that you have this option ...

World, -Al

+3
source share

All Articles