3

I am trying to read a COBOL data file using JRecord, in that I have a Header record and Detail record, so I parsed with SPLIT_01_LEVEL and CopyBook File format as FMT_OPEN_COBOL. I have few date fields in the flat file as COMP-3 fields, and I am unable to understand on how to convert them into Java Date fields.

ICobolIOBuilder iob = CobolIoProvider.getInstance()
                 .newIOBuilder(copybookName)
                     .setCopybookFileFormat(Convert.FMT_OPEN_COBOL)
                     .setSplitCopybook(CopybookLoader.SPLIT_01_LEVEL);
//I fetched fields as below
line.getFieldValue(field).asString();

The CopyBook have fields as

MPOH-ENTRY-DATE              PIC S9(7) COMP-3.
MPOH-STATUS-DATE             PIC S9(7) COMP-3.
MPOH-APPROVED-DATE           PIC S9(7) COMP-3.
MPOH-ORDER-DATE              PIC S9(7) COMP-3.

When I parsed as above the output is

MPOH-ENTRY-DATE : 11261a1
MPOH-STATUS-DATE : 11261a1
MPOH-APPROVED-DATE : 11261a1
MPOH-ORDER-DATE : 11266140

Please help me in converting these fields to Java Date fields.

Bruce Martin
  • 10,358
  • 1
  • 27
  • 38
java-ocean
  • 59
  • 1
  • 10
  • Oh wow. I thought my COBOL days were done with... Could you please try and get **binary representation** of that input? As stated in http://www.3480-3590-data-conversion.com/article-packed-fields.html the numbers are stored as packed decimal - maybe there already is some code for conversion out there, otherwise I'd love to write some. – Jan Dec 04 '15 at 17:24
  • Hmm - seems like JRecord already has that (darn.) seems like you need to `asInt()` value from field instead of `asString()` – Jan Dec 04 '15 at 17:38
  • 1
    Since your fields all all seven digits, the eight characters in the final date are suspect. Obviously the lower-case a is incorrect in the others, but can you confirm the value in the last field. OK, seven digits, so what is the format of the date expected? As previously asked, hex values of those fields would be good. – Bill Woodger Dec 04 '15 at 20:15
  • 1
    Since the date fields are seven digits, I'm guessing the format is a Julian yyyyddd. 2015338 (Dec 4, 2015), as an example, would be stored in COMP-3 as x20 x15 x33 x8F – Gilbert Le Blanc Dec 04 '15 at 20:29
  • Is the data really coming from GNU Cobol ??? – Bruce Martin Dec 04 '15 at 23:36

2 Answers2

6

The big problem is there has been an EBCDIC to ascii conversion.

The JRecord builder creation

ICobolIOBuilder iob = CobolIoProvider.getInstance()
             .newIOBuilder(copybookName)
                 .setCopybookFileFormat(Convert.FMT_OPEN_COBOL)
                 .setSplitCopybook(CopybookLoader.SPLIT_01_LEVEL);

does not include the setFont, so on a Unix / Linux / Windows PC, this indicates the file is ASCII. Which is not good if you are running on Window / Linux / Unix and the file was created on the mainframe, Also is the Data really comming from GNUCobol ???.

The data looks to has been through a EBCDIC -> Ascii conversion ??? or possibly shifted by 1 byte. If it really is GNU_Cobol you may need one of the other formats e.g. FMT_OPEN_COBOL_MVS


All 4 of the following numbers are not valid comp-3 numbers:

MPOH-ENTRY-DATE : 11261a1
MPOH-STATUS-DATE : 11261a1
MPOH-APPROVED-DATE : 11261a1
MPOH-ORDER-DATE : 11266140

The MPOH-ORDER-DATE is now x'11 26 61 40' while the EBCDIC original may of been x'11 50 81 7c' i.e.

CYY = 115 (or 2015)
 MM =  08 
 DD =  17

So you need to

  1. A binary transfer to Get the raw EBCDIC file. If it is a RECFM=VB file on the mainframe, convert it to RECFM=FB first.
  2. Add setFont("cp037") to the IOBuilder step (if you are using US ebcdic. There are different EBCDIC's for different countries e.g. cp273 for germany) .

    ICobolIOBuilder iob = CobolIoProvider.getInstance()
             .newIOBuilder(copybookName)
                 .setCopybookFileFormat(Convert.FMT_MAINFRAME)
                 .setSplitCopybook(CopybookLoader.SPLIT_01_LEVEL)
                 .setFont("cp037");
    
  3. For what it worth, the Dates look to be in a CYYMMDD format where C=0 is 1900 and C=1 is 2000


If I am not correct, please provide the raw data and the Copybook

The other alternative is a 1 byte error in the copybook displacement

e.g.

MPOH-ENTRY-DATE : 1?11261
MPOH-STATUS-DATE : 1?11261
MPOH-APPROVED-DATE : 1?11261
MPOH-ORDER-DATE : 112661

But it does not look like a Date ???


There not a big difference between Convert.FMT_MAINFRAME and Convert.FMT_OPEN_COBOL. But these are the differences:

  • GNU Cobol has 1, 2 ,4, 8 byte binary integers while the mainframe has 2, 4, 8
  • Comp-5 in GNU-Cobol (on intel hardware) is little ending (mainframe is big-endian).
  • Zoned decimal is different
  • different floating point (comp-1, comp-2).

The following fields are where you would seee a difference:

03 f1              pic s9(3).
03 f2              pic s99 comp.
03 f3              pic s9(4) comp-5  
03 f4     comp-1.
03 f5     comp-2.
Bruce Martin
  • 10,358
  • 1
  • 27
  • 38
  • @Bruce Martin, I am not sure if its GNU Cobol or not, And I am not sure if the file I received is raw ebcdic file or if it was reformatted. I am trying to find the right person to answer these questions. Mean while I tried to set the Font as cp037 on my windows, I am getting wrong values or some special characters. But if I dont use any font then I am able to fetch values for at least few fields(other than COMP-3 fields) which I am able to recognize in the file. – java-ocean Dec 10 '15 at 20:51
  • You have tagged the question as Mainframe, if it is genuinely from a IBM Mainframe (ZOS), it is almost certainly FMT_Mainframe. If it is IBM AS-400, try FMT_Mainframe. What Operating System is the Cobol file from. Also ask what the cobol Compiler they are using – Bruce Martin Dec 10 '15 at 21:10
  • I could not get more info on the file, I think I didn't get the raw file and thats the reason for wrong values. Since I couldn't validate, I cannot select any answer as correct one. And now I moved to a different project. – java-ocean Jan 25 '16 at 21:39
1

From the Docs and how JRecords seems to be setup, you should be able to replace

line.getFieldValue(field).asString();

with

line.getFieldValue(field).asInt();

to get some meaningful result. If that int will be 20151204 or something else entirely remains to be seen - but if I remember my COBOL days correctly, it's probably yyyyMMdd just stored as number

Jan
  • 13,738
  • 3
  • 30
  • 55
  • Thanks for your response, when I try as you suggested I am getting error as `java.lang.NumberFormatException: For input string: "11261a1"` and since its 7 digits rather than 8 I am not sure if we can go with yyyyMMdd – java-ocean Dec 04 '15 at 18:38
  • 1
    Thats strange. Could you share enough code to make a running example? And what did you change exactly? – Jan Dec 04 '15 at 18:40
  • Do you imply thar Bruce's answer didn't resolve it? What did you change so far? – Jan Dec 10 '15 at 20:38
  • The code I used is `while((line = reader.read()) != null){ Map fieldNameMap = line.getLayout().getFieldNameMap(); for(String field : fieldNameMap.keySet()){ if(field.indexOf("DATE") > 0){ System.out.print(field + " : "+line.getFieldValue(field).asInt() + "\t"); } } }` – java-ocean Dec 10 '15 at 20:40
  • Bruce answer was helpful in understanding a lot about JRecord and other cobol related things. Thats the reason I upped Bruce's answer. I am still trying to work the way Bruce has suggested. – java-ocean Dec 10 '15 at 20:41