Hi Bruce - I am trying to use JRecord to convert a Mainframe file (transferred to linux as binary) that has COMP and COMP-3 fields to a csv ascii file. Within my corporate environment I don't have access to cobl2csv.jar. I only have access to cb2xml.jar and Jrecord.jar. How can I use these 2 Jar's to convert the file to csv? Appreciate your help. Thanks!
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
But here is a basic example of the logic (I will do an enhanced version in the morning)
try{ICobolIOBuilderiob=JRecordInterface1.COBOL.newIOBuilder(copybookName).setFont("cp037")// US EBCDIC.setFileOrganization(IFileStructureConstants.IO_FIXED_LENGTH_RECORDS);AbstractLineReaderreader=iob.newReader(dataFile);AbstractLineline=reader.read();if(line!=null){Stringsep="";FieldIteratorfieldIterator=line.getFieldIterator(0);for(AbstractFieldValuefv:fieldIterator){System.out.print(sep+fv.getFieldDetail().getName());sep=",";}System.out.println();while(line!=null){sep="";for(AbstractFieldValuefv:fieldIterator){System.out.print(sep+fv.asString());sep=",";}line=reader.read();}}reader.close();}catch(Exceptione){System.out.println("~~> "+e.getMessage());System.out.println();e.printStackTrace();}
Last edit: Bruce Martin 2022-11-04
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Here is an updated (and better version) version using JRecord's CSV writer:
try{ICobolIOBuilderiob=JRecordInterface1.COBOL.newIOBuilder(copybookName).setFont("cp037")// US EBCDIC.setFileOrganization(IFileStructureConstants.IO_FIXED_LENGTH_RECORDS);AbstractLineReaderreader=iob.newReader(dataFile);ICsvIOBuildercsvOBuilder=JRecordInterface1.CSV.newIOBuilder(",","\"");IDefineCsvFieldscsvFields=csvOBuilder.defineFields();AbstractLineline=reader.read();if(line!=null){FieldIteratorfieldIterator=line.getFieldIterator(0);for(AbstractFieldValuefv:fieldIterator){csvFields.addCsvField(fv.getFieldDetail().getName(),Type.ftChar,0);}csvOBuilder=csvFields.endOfRecord();ByteArrayOutputStreambyteArrayOutputStream=newByteArrayOutputStream();AbstractLineWritercsvWriter=csvOBuilder.newWriter(byteArrayOutputStream);while(line!=null){AbstractLinecsvLine=csvOBuilder.newLine();intfldNum=0;for(AbstractFieldValuefv:fieldIterator){csvLine.getFieldValue(0,fldNum++).set(fv.asString());}csvWriter.write(csvLine);line=reader.read();}csvWriter.close();System.out.println(byteArrayOutputStream.toString());}reader.close();}catch(Exceptione){System.out.println("~~> "+e.getMessage());System.out.println();e.printStackTrace();}
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Thanks for your response Bruce. My input file is Variable Block, with multiple 01 levels. There is a field-type that will help use the right 01 level. How should I handle it?
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
For Multiple records you will need .setSplitCopybook(CopybookLoader.SPLIT_01_LEVEL) in the ioBuilder.
The line.getFieldIterator(0) takes either a record-index or record-name as a parameter
So
ICobolIOBuilderiob=JRecordInterface1.COBOL.newIOBuilder(copybookName).setSplitCopybook(CopybookLoader.SPLIT_01_LEVEL).setFont("cp037")// US EBCDIC.setFileOrganization(IFileStructureConstants.IO_FIXED_LENGTH_RECORDS);
To determine the the Record-Type you can use:
Java code - i.e. test the field in java
Use the .setRecordSelection to tell JRecord how to distinguish the record-type
Use RecordDecider to tell JRecord how to distinguish the record-type
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
So, the file I am reading is a fixed length file (i had wrongly mentioned earlier that it is VB). I have multiple 01 level records with the first one being basic structure (say first 100 bytes) and the subsequent 01 levels are to be applied based on the record-type field that is in the basic structure. Kind of like below.
Fo the record selection, I am doing
if (line.getFieldValue("Basic-struc-field2") ..asInt() == 1 ) {
}
I know I can also use a case switch stmt.
The issue I am facing is, I am able to successfully read the first record, but not able to read the subsequent records as I am getting the following error when again doing line.getFieldValue("Basic-struc-field2).
I am not using the FieldIterator to read the field values. Instead I am using like shown above - line.getFieldValue("field-name"). Maybe I should use the FieldIterator? If so, how do I assign the record-index/record-name?
Last edit: RAJKUMAR VISWANATHAN 2022-11-16
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Hi Bruce, at this point I just need to know how to iterate through each of the records in the file. Like I said, I am able to read the first record. It is the subsequent records that I am having trouble with. Should I used the Field Iterator or line.getFieldValue("Field-Name")? I am currently using the line.getFieldValue("Field-Name").
Thanks for your help!
Last edit: RAJKUMAR VISWANATHAN 2022-11-16
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
AbstractLinesaleRecord;ICobolIOBuilderiob=JRecordInterface1.COBOL.newIOBuilder(copybookName).setFont("cp037")// US EBCDIC.setFileOrganization(IFileStructureConstants.IO_FIXED_LENGTH_RECORDS);AbstractLineReaderreader=iob.newReader(salesFile);while((saleRecord=reader.read())!=null){}
If the lines are not correctly formatted then either:
The wrong **FileOrganisation is being used
There is problems with the file.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Thanks Bruce. So, every time it iterates through the "while" loop and does reader.read(), does it read each record from the input file? How does it know how many bytes to read for each record? From the copybook in .newIOBuilder(copybookName)?
Last edit: RAJKUMAR VISWANATHAN 2022-11-17
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I got it to work. Basically, the copy book I was given for the data was wrong.
Also, looks like in case of multiple 01 level records (each 01 of different length), the application takes the length of the longest record and applies that when reading the input file.
Thanks for all your help Bruce! Your app is very helpful!
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Sine my input is a Variable Block file with each record of different length, am I to use .setFileOrganization(Constants.IO_VB)? When I do that, I am getting ArrayIndexOutOfBoundsException when I try to check the field to determine the Record-Type (to determine which 01 level to use).
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
By default some file transfer options will drop the record-lengths when transferring a file. This is what has probably happened. There is an option (quite possibly called RDW) to transfer both the record-length and the Data.
If you supply a Sample file to the CodeGen option in the RecordEditor, it will look for Record-Lengths (Record-descriptor-word)
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Hi Bruce - I am trying to use JRecord to convert a Mainframe file (transferred to linux as binary) that has COMP and COMP-3 fields to a csv ascii file. Within my corporate environment I don't have access to cobl2csv.jar. I only have access to cb2xml.jar and Jrecord.jar. How can I use these 2 Jar's to convert the file to csv? Appreciate your help. Thanks!
You will need to work out the parameters to use for the
IoBuilder
. The RecordEditor can help with this, see https://sourceforge.net/p/jrecord/wiki/Generate%20Code%20for%20Binary%20Cobol%20file/But here is a basic example of the logic (I will do an enhanced version in the morning)
Last edit: Bruce Martin 2022-11-04
Here is an updated (and better version) version using JRecord's CSV writer:
Thanks for your response Bruce. My input file is Variable Block, with multiple 01 levels. There is a field-type that will help use the right 01 level. How should I handle it?
For Multiple records you will need
.setSplitCopybook(CopybookLoader.SPLIT_01_LEVEL)
in the ioBuilder.The
line.getFieldIterator(0)
takes either a record-index or record-name as a parameterSo
To determine the the Record-Type you can use:
.setRecordSelection
to tell JRecord how to distinguish the record-typeRecordDecider
to tell JRecord how to distinguish the record-typeSo, the file I am reading is a fixed length file (i had wrongly mentioned earlier that it is VB). I have multiple 01 level records with the first one being basic structure (say first 100 bytes) and the subsequent 01 levels are to be applied based on the record-type field that is in the basic structure. Kind of like below.
How do I iterate through each record?
Thanks!
Last edit: RAJKUMAR VISWANATHAN 2022-11-16
Fo the record selection, I am doing
if (line.getFieldValue("Basic-struc-field2") ..asInt() == 1 ) {
}
I know I can also use a case switch stmt.
The issue I am facing is, I am able to successfully read the first record, but not able to read the subsequent records as I am getting the following error when again doing line.getFieldValue("Basic-struc-field2).
net.sf.JRecord.RecordException. Basic-struc-field2: Invalid Zoned Decimal:
I am not using the FieldIterator to read the field values. Instead I am using like shown above - line.getFieldValue("field-name"). Maybe I should use the FieldIterator? If so, how do I assign the record-index/record-name?
Last edit: RAJKUMAR VISWANATHAN 2022-11-16
I suggest trying to view the file in the RecordEditor.
See https://stackoverflow.com/questions/45794642/how-do-you-edit-a-binary-mainframe-file-in-the-recordeditor-using-a-cobol-copybo
Also the USB version of the RecordEditor does not need to be installed on a computer.
Hi Bruce, at this point I just need to know how to iterate through each of the records in the file. Like I said, I am able to read the first record. It is the subsequent records that I am having trouble with. Should I used the Field Iterator or line.getFieldValue("Field-Name")? I am currently using the line.getFieldValue("Field-Name").
Thanks for your help!
Last edit: RAJKUMAR VISWANATHAN 2022-11-16
The basic logic should be:
If the lines are not correctly formatted then either:
Thanks Bruce. So, every time it iterates through the "while" loop and does reader.read(), does it read each record from the input file? How does it know how many bytes to read for each record? From the copybook in .newIOBuilder(copybookName)?
Last edit: RAJKUMAR VISWANATHAN 2022-11-17
I got it to work. Basically, the copy book I was given for the data was wrong.
Also, looks like in case of multiple 01 level records (each 01 of different length), the application takes the length of the longest record and applies that when reading the input file.
Thanks for all your help Bruce! Your app is very helpful!
Sine my input is a Variable Block file with each record of different length, am I to use .setFileOrganization(Constants.IO_VB)? When I do that, I am getting ArrayIndexOutOfBoundsException when I try to check the field to determine the Record-Type (to determine which 01 level to use).
.setFileOrganization(Constants.IO_VB) is correct, the problem is almost certainly the file transfer.
On the mainframe a VB file consists of
By default some file transfer options will drop the record-lengths when transferring a file. This is what has probably happened. There is an option (quite possibly called RDW) to transfer both the record-length and the Data.
If you supply a Sample file to the CodeGen option in the RecordEditor, it will look for Record-Lengths (Record-descriptor-word)