0

In a job I will treat two types of files. I need to select files by size because whichever is go to one program or another.

Currently, I am getting every day a file of a length of 200 positions (LREC=200,FB) by EDITRAN , but now I can get a 200 or 400 positions. I want to make a difference in my chain if one size or another , to use it as usual or new programs.

The selection should be with jcl. Does anyone know how to do this ?

Thanks for your help

  • You need to describe this better, with some sample of your input files, and the expected output. Are there any "trailers" on the files, indicating number of records? By "size", do you mean total bytes, number of records, or something else? – Bill Woodger Oct 03 '15 at 18:05
  • Thanks Bill, I've trying explain better. – Felipe Rodriguez Fonte Oct 03 '15 at 19:17

1 Answers1

0

OK, has to be done, so make it secure...

First step:

//GETSYSL  EXEC PGM=SORT 
//SORTOUT  DD DUMMY 
//SYSOUT   DD DISP=(,PASS),DSN=&&SOUT, 
// UNIT=SYSDA,SPACE=(TRK,1) 
//SORTIN   DD DISP=SHR,DSN=yourinputdsn
//SYSIN    DD * 
  OPTION COPY,STOPAFT=1 

This copies the first record of your input dataset to SORTOUT, which is set to DUMMY in the JCL. One record due to the STOPAFTer.

The point of the step is that in the SYSOUT, DFSORT will list the LRECL of the input file.

So output the SYSOUT to a dataset (can be permanent, I used a temporary for testing).

Then process the sysout in the dataset:

I have coded using DFSORT symbols/SYMNAMES, to make it easier to understand. In your JCL you need:

//SYMNAMES DD DISP=SHR,DSN=yourpdsforsymnames(yourmem)
//SYMNOUT DD SYSOUT=yoursitestandard

The member contains the source symbols, the output list shows the source symbols for reference, and how DFSORT has normalised them prior to applying them.

There are four output datasets, SORTOUT will contain a copy of the SYSOUT from the previous step (the input file to this step) and a message if something bad has happened. The other three can all be set to DUMMY, as it is only the RC which is relevant: RC=0 means Record-length of 400, RC=4 means record-length of 200, RC=16 means something bad, perhaps an error in the control cards, perhaps an error with the file (not 200 or 400), and you should halt the process and investigate.

Here's the code, using DD * for SYMNAMES and SORTIN and SYSOUT=* instead of dummy for my testing:

//DETLEN   EXEC PGM=SORT                  
//SYSOUT   DD SYSOUT=* 
//SORTOUT  DD SYSOUT=* 
//SYMNAMES DD * 
INP-RECORD,*,129,CH 
INP-CC,=,1,CH 
INP-DATA,*,120,CH 
EXTENDED-INPUT-RECORD,*,1 
EXT-LENGTH,=,4,CH 
EXT-PUSH-LENGTH,*,4,CH 
POSITION,INP-DATA 
INP-MESSAGE-CODE,=,8,CH 
POSITION,INP-DATA 
SKIP,119 
LAST-OF-DATA,*,1,CH 
ICE088I-WITH-LENGTH,C'ICE088I ' 
ICE088I-END-MESSAGE,C'ICE052I ' 
EQUALS-BLANK-BEFORE-LEN,C'= ' 
COMMA-AFTER-LENGTH,C',' 
LENGTH-200,C'200 ' 
LENGTH-400,C'400 ' 
EXTRACTED-LENGTH,%00 
HEADING-FOR-SYSOUT,C'SYSOUT FROM STEP TO DETERMINE LENGTH' 
//SYMNOUT DD SYSOUT=* 
//IS200 DD SYSOUT=* 
//IS400 DD SYSOUT=* 
//CHECK DD SYSOUT=* 
//SORTIN   DD DSN=&&SOUT,DISP=(OLD,PASS) 
//SYSIN    DD * 
  OPTION COPY 
  INREC IFTHEN=(WHEN=INIT, 
      PARSE=(EXTRACTED-LENGTH=(STARTAFT=EQUALS-BLANK-BEFORE-LEN,
                             ENDBEFR=COMMA-AFTER-LENGTH, 
                             FIXLEN=4)), 
                 OVERLAY=(EXT-LENGTH: 
                           EXTRACTED-LENGTH)), 
        IFTHEN=(WHEN=GROUP, 
                 BEGIN=(INP-MESSAGE-CODE, 
                       EQ, 
                      ICE088I-WITH-LENGTH), 
                 PUSH=(EXT-PUSH-LENGTH:EXT-LENGTH)), 
        IFTHEN=(WHEN=(INP-MESSAGE-CODE, 
                       NE, 
                      ICE088I-WITH-LENGTH), 
                 OVERLAY=(EXT-LENGTH:4X)) 

  OUTFIL HEADER1=(HEADING-FOR-SYSOUT), 
        IFTHEN=(WHEN=(INP-MESSAGE-CODE, 
                       EQ, 
                      ICE088I-END-MESSAGE, 
                   AND, 
                  (EXT-PUSH-LENGTH,NE,LENGTH-200, 
                    AND, 
                   EXT-PUSH-LENGTH,NE,LENGTH-400)), 
               BUILD=(INP-RECORD, 
                      /, 
                      C'SOMETHING WICKED THIS WAY COMES', 
                      EXT-PUSH-LENGTH, 
                      LAST-OF-DATA:X)) 

  OUTFIL FNAMES=IS200, 
         INCLUDE=(EXT-LENGTH,EQ,LENGTH-200), 
         NULLOFL=RC4 

  OUTFIL FNAMES=IS400, 
         INCLUDE=(EXT-LENGTH,EQ,LENGTH-400), 
         NULLOFL=RC0 

  OUTFIL FNAMES=CHECK, 
         INCLUDE=(INP-MESSAGE-CODE,EQ,ICE088I-END-MESSAGE,
                   AND, 
                  (EXT-PUSH-LENGTH,EQ,LENGTH-200, 
                    OR, 
                   EXT-PUSH-LENGTH,EQ,LENGTH-400)), 
         NULLOFL=RC16 

PARSEs for the record-length, even though the current record may not contain the information.

Uses WHEN=GROUP, with a BEGIN identifying the message containing the length, so that each subsequent record contains the length (important for the final record).

Clobbers the original length field if not a length record (the PARSEd value is still separate).

Then the OUTFILs swing into action, using INCLUDE= on the extracted record-length (could also be the PUSHed record-length, it would not matter).

SORTOUT copies the input, and, when the final record arrives (by message number) checks that a valid length on a correct record was found, otherwise puts out a message as well (you may change the text).

CHECK does the same as the checking in SORTOUT, except ensures an RC=16 by writing no data.

With SORT, the only way to set the RC other than by error is with empty output datasets (SORTOUT empty uses OPTION NULLOUT... and an OUTFIL uses NULLOFL).

Note, a simple error in the control cards of the second step will also get an RC=16.


The method is wrong.

A produces a file with 200-byte records. B produces a file with 400-byte records. (A and B could be the same program, it doesn't matter).

If A has run, that fact should be used to determine which program processes the file. Equally if B has run.

If you just look at the file, and decide based on the record-length, then you leave yourself open to processing a bad file, just because you found a 200-byte-record file, even though B actually ran.

The best way to do this is to have a Header record on the file. The header record should contain a unique identifier, the data-date (effective business date for the file), the environment it is from (PROD, for instance, or SYST for System Testing or whatever) and a logical name for the file, which is different for the two types of records, or a further indicator of the difference. It may contain other information as well. Anything that is useful.

The header should be written as part of the process of A or B producing the data, not added later (unless allowing similar checking that the header being added actually belongs to the data).

All information on the header should be checked, and the file processed, by the correct receiving program, if all the information is as expected.

If you need an interim solution before that can be implemented:

Using DFSORT, do a COPY with OPTION STOPAFT=1; send the SYSOUT for that step to a dataset; in a second step process the sysout to identify the ICE088I message, and extract the LRECL, which will be 200 or 400; use three OUTFILs, one to copy the input to a SYSOUT dataset (so that you can see it in the JOB output, although a step later); another OUTFIL where the message is written if it is 200; the third OUTFIL where the record is written if it is 400; use NULLOFL=RC4 for one of the "length" OUTFILs; the step will terminate with RC=0 for one length and RC=4 for the other; you should further code to give an RC=16 if the file is neither 200 or 400; so four OUTFILs - use the ICE052I message for that test.

Bill Woodger
  • 12,968
  • 4
  • 38
  • 47
  • First, thanks Bill. I know my method is dirty, the problem is these files are sending to my system since a lot of companies. The clean solution is change de lenght of file because the file with 400 bytes of size is same that 200 byte but It have extra information. But, I can't change the lenght of files of other companies. Other method is create other jcl same structure but I will treat the file of 400 bytes. Really, I don't like because I should involve other departament (by EDITRAN). – Felipe Rodriguez Fonte Oct 04 '15 at 08:52
  • My last boss tell me other solucion with listcat and then a program un COBOL read the file of listcat... I think that I could use icetool or dfsort for treat the file... – Felipe Rodriguez Fonte Oct 06 '15 at 21:34
  • 1
    You can of course use LISTCAT, and even process that output with DFSORT/ICETOOL. I chose the DFSORT SYSOUT as the source because the data wanted has a message number on it. However, LISTCAT has the benefit of allowing you to get the datasetname in the output as well. I'll add that tomorrow if I get a moment, it'll be a good example of the flexibility of using the symbols. – Bill Woodger Oct 07 '15 at 02:58
  • Thanks Bill, I never have used symbols, and I think is a good example. – Felipe Rodriguez Fonte Oct 08 '15 at 07:07