I referred a code on the internet to unpack comp 3 to numeric in java. I tried to pass a sample comp3 file to the code but I didn't get the proper unpacked data. I got some weird numbers. I am new to this concept(comp 3) so can you guys help me on this. Thanks in advance
Below is my code
import java.math.BigInteger;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
/**
* Converts between integer and an array of bytes in IBM mainframe packed
* decimal format. The number of bytes required to store an integer is (digits +
* 1) / 2. For example, a 7 digit number can be stored in 4 bytes. Each pair of
* digits is packed into the two nibbles of one byte. The last nibble contains
* the sign, 0F for positive and 0C for negative. For example 7654321 becomes
* 0x76 0x54 0x32 0x1F.
*
* This class is immutable. Once constructed you can extract the value as an
* int, an array of bytes but you cannot change the value. Someone should
* implement equals() and hashcode() to make this thing truly useful.
*/
public class PackedDecimalToComp {
public static void main(String[] args) {
try {
// test.unpackData(" 0x12345s");
Path path = Paths.get("C:\\Users\\AV00499269\\Desktop\\Comp3 data file\\Comp3Test.txt");
byte[] data = Files.readAllBytes(path);
PackedDecimalToComp test = new PackedDecimalToComp();
test.unpackData(data);
} catch (Exception ex) {
System.out.println("Exception is :" + ex.getMessage());
}
}
private static String unpackData(byte[] packedData) {
String unpackedData = "";
final int negativeSign = 13;
for (int currentCharIndex = 0; currentCharIndex < packedData.length; currentCharIndex++) {
byte firstDigit = (byte) ((packedData[currentCharIndex] >>> 4) & 0x0F);
byte secondDigit = (byte) (packedData[currentCharIndex] & 0x0F);
unpackedData += String.valueOf(firstDigit);
if (currentCharIndex == (packedData.length - 1)) {
if (secondDigit == negativeSign) {
unpackedData = "-" + unpackedData;
}
} else {
unpackedData += String.valueOf(secondDigit);
}
}
System.out.println("Unpackeddata is :" + unpackedData);
return unpackedData;
}
}
Comp3 file I passed has values x019F
When converted I got the unpacked data as 783031394
You can use the IBM Record Generator for Java, a free tool.
This allows you to generate a Java class that represents a COBOL or PL/I DSECT which you can then use in your own code to read/write values to most COBOL and PL/I data types. If you aren't working with a structure then you can see through the code how the underlying JZOS classes are used to interact with the datatype.
Although the tool is free it is supported by IBM, so if you hit an issue you can raise a problem with IBM and they will fix it.
Handling Mainframe binary file
You have 2 options:
- Convert the file to a Text file on the mainframe and then transfer the file
- Do a binary transfer and keep the file as EBCDIC then use something like JRecord to read the file. You can also use RecordEditor to edit the file
I have also seen files converted to Unix EBCDIC Text files on the mainframe and a binary Transfer (keep as EBCDIC). This is done for non-English EBCDIC where you have special language specific characters. Java editors (e.g. JEdit) have no trouble editing Unix Ebcdic files
File Transfer (Mainframe)
To transfer a Binary file (has comp, comp-3 etc) from the Mainframe to
Windows / *nix box you must do a Binary Transfer for a very simple reason: the Ebcdic --> Ascii program can not distinguish between binary fields and Text fields.
Comp-3 value hex hex after Ascii conversion
400 x'400c' x'200c' x'40' is the ebcdic space character
it gets converted to the ascii
space character x'20'
You need to do a Binary transfer from the Mainframe. This will keep the file as EBCDIC and any binary fields will be untouched. You then read the file using Ebcdic.
You will need to check the RECFM on the Mainframe. If the RECFM is
- FB - no problems just transfer
- VB - either convert to FB on the mainframe of include the RDW (Record Descriptor Word) option in the file transfer.
- Other - Convert to FB/VB on the mainframe
RecordEditor
- Make sure you have Java installed
- You can get the RecordEditor from here. You can either download an installer or the USB version. The USB version is a zipped Directory which you can install in any normal directory.
Using The Record Editor
You need to define the Record Layout (or file schema). The easiest way is to import a Cobol Copybook.
For a 2 byte comp-3 field, create a cobol copybook with
01 Tst-Record.
03 comp3-field pic s9(3) comp-3.
To import the cobol copybook Select Record Layouts >>> Load Cobol Copybook
Then enter the Cobol copybook file name and press the load Cobol button at the bottom of the screen
Next go the file open screen and enter the file name and select the copybook you have just imported:
Hit enter and you should be able update the file:
Generating Code
The RecordEditor can also generate code for the JRecord Library. See How do you generate java~jrecord code for a Cobol copybook for hot to generate Java~JRecord Code using a Cobol Copybook.
You can also generate Code that does not use a Cobol Copybook wile editting the file:
Select Generate >>> Generate Code from the File option. Thene select a template and enter a package Id