Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations IamaSherpa on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

How to Input Variable Length Record File 2

Status
Not open for further replies.

rasETL

IS-IT--Management
May 28, 2003
213
US
I have a COBOL process running in IBM Z/OS.

I have a process where I would like to allow file(s) with any record length to be input. I have left the "RECORD CONTAINS" clause out of the program, and by specifiying the LRECL in the JCL, can get File(s) in no prblem.

The problem, however, is when reading the records. I have set up the FD area as PIC X(2000) so records up to that length can be processed. This causes COBOL to return 2000 bytes of information for each record, regardless of their length.

Example, if the record is 100 bytes long, the 1st READ brings in the first 20 records, the 2nd READ bring in records 2-21, the 3rd brings in 3-22, etc. You will notice the program recognizes the records, but bring in additional data to fill the 2000 bytes.

We have tried READ...INTO and READ FD then MOVE, and both have the same bad result.

Does anyone know how to eliminate this from happening without knowing the actual Record Length?

 
In the pc-environment we work for years with fb records which can be read in one single file definition; no problem at all. IBM made such a behaviour available for the mainframe with RECORD 0. Very easy.

That you don't know what the original length of your record is, that is strange. Why is it important? If it is important, why doesn't contain the record a RECORD-TYPE or something that identifies it? Why do you want to process all the different files in one FD?

If you want only to process the data inside, use READ ... INTO and you don't get other data than from the current record. If your current record ends with spaces, pitty. You probably don't have any processing to do for those spaces so what is the problem? The READ ... INTO can be qualified as a work-around but what is the problem with a work-around. IBM doesn't have the statement LENGTH OF CURRENT-RECORD OF FILE .... yet, but until it is there the READ ... INTO will work fine.
 
Hi Crox,

It seems what we're doing here is trying to solve a problem with no (or little) definition. Rsaanders seems unwilling to share info regarding the problem or deems our questions irrelevent.

Under those circumstances my final reply is "Goodbye, Rsaanders. Don't let the door hit you..."

Regards, Jack.
 
Hi Jack,

I agree with you.
Why are we doing this?

Regards,

Crox
 
This is slightly off-topic, byt WMK suggested that the original thread submitter use a true V or VB file as input. I've never used V or VB as input, only as output (multiple 01 formats going to same file, each 01 having its own fixed length).

So, can someone tell me how one reads V/VB and knows the actual length of the input record? Is the first 4-bytes of the physical record (that contain the record length) available to the application program?

A short code segment, if available and convenient, would be much appreciated. Thanks!

Craig
 
What you ask was pretty difficult with OS/VS COBOL (and '74 Standard compilers). It required "negative subscripting) and all sorts of other work arounds.

With the '85 Standard (and VS COBOL II and later IBM compilers), it is possible to code the following type of RECORD CONTAINS clause under your FD.

Record Varying in Size
From 1 to 999
depending on WS-Item

You define WS-Item in your WS and after every READ, the WS-Item will contain the size of the record that was read.

(You need some other "stuff" - but this is the basic functionality).

You must, however, know the maximum record size at compile time - which is why the original question in this thread poses a problem.

Bill Klein
 
I hope that no one is upset with me for resurrecting this thread, but I need some more guidance.

ENVIRONMENT: MVS, JCL, current Cobol compiler (sorry, I don't know which one!)

GOAL: a "black box" utility which takes two input files (specified in JCL) and a set of user parms from SYSIN to manipulate fields within these two files. The user parms specify byte offsets to work with, etc. At compile time, the program does not know if the files are FB or VB, and does not know the LRECL. It would be best to determine these programatically, but it is acceptable that the user identify this information in the SYSIN parms.

STATUS: I have it working programatically (from info I obtained from these threads) for FB files, and the user can specify in SYSIN whether the files are F or V. The sizes for "F" are determined from the OS and this works well. However, for "V", I can currently only get it to support a single "V" size (arbitrarily 4,004).

PROBLEM: I want to support any "V" LRECL size, up to 10,004, without having to recompile for the specific size. This is working for "F", now to get it for "V".

FLEXIBILITY: I prefer the solution to be all-Cobol, but I am willing to use an assembler helper program. Perhaps even "C", although I don't know if they have "C" at this installation (this is a services job), so it would have to be something I could provide as an OBJECT text for linking into the program.

OTHER: I have not yet made the output files to be dynamic length, either, but that will be the next step. Similar to the above, the user parms or the JCL allocation (the output files are new files) would be the source of the size information at run time.

Any help would be appreciated and if I'm rehashing old stuff, please gently put me in my place!

Thanks, Craig
 
Fresh PC Cobol point of view here ...

How about opening the file in binary mode and reading chunks of (for example) 20,000 bytes? If you're guaranteed that the files are text only, and are line sequential, then just read one of those records at a time and then unstring them delimited by x"0d" (line feed, if I'm not mistaken). You'll have to do some creative stitching in order to join the last characters in this buffer to the first characters in the next buffer you'll read, but that's about it.

All you'll have to do is unstring the buffer one x"0d" delimited section at a time, and move it into your FD section. No extra characters will be found with this method.

If you on record sequential files, though, this will not work for you. I'm not sure what to do in that case.

.DaviD.
 
David, thanks for the quick response, but I don't think that there is an open binary for IBM MVS. Also, my files are not line-oriented display, but pure data records.

Any other ideas?
 
Make your FD for VB files the largest possible size and it will handle anything up to that, won't it? Otherwise, you may have to read them as RECFM=U and break them up yourself.

Regards.

Glenn
 
Glenn,

That was my first thought as well -- make it 10,000 in the Cobol code, and any file up to that limit would work. Makes sense but, unfortunately, the OPEN fails on the LRECL mismatch. Illogical to me, but there's probably a valid explanation somewhere.

I'd be game to try the RECFM=U, but never done so before -- is there any sample program I can steal from? A complete FD & matching 01 record might be sufficient ...

Thanks, Craig
 
Am I correct that the files will all be QSAM (no VSAM)? If so, you can SORT-OF handle this "all in cobol" by pretending you are doing it in Assembler. (I haven't tried this - but I *think* it will work)

What you need to do is define your FD as RECORDING MODE is U. Then before you do your OPEN, you do a CALL to a subprogram and pass it the FD name (not the record name).

That subprogram will get the DCB in its linkage section. You then need to "play" with the DCB (which is why I say that you need to work as if you were in assembler) filling in all the information the way you want it to be for this particular file. You will need to use the data management manuals to figure out exactly what needs to be filled in and how - and you will use "USAGE POINTER" items like crazy <G>

When you return to your main program you should be able to do I/O correctly with the "specifics" for this file.

***

Basically, IBM COBOL itself is set up pretty much to PREVENT one from doing what you are trying. Therefore, this is pretty nasty to accomplish (much less maintain).

Personally, if I had a REQUIREMENT for what you are trying to do, I would:

A) do it in Assembler itself
or
B) Use ISPF library services (that can be used in batch) to do all the file I/O.

Bill Klein
 
Bill,

Thanks for the ideas. Yes, it is QSAM, not VSAM. Adding your ideas to the one solid one I was given earlier, it appears there are three possibilities:

1. Code the "V" input files as "U"
2. Code a Cobol subprogram to manipulate MVS data blocks to make Cobol think I had defined the FD as the numbers that the file really has
3. Code an assembler subprogram to manipulate MVS data blocks (see #2)

At first look, I think that #1 is the most straight-forward, but: (a) I have no idea how to do this -- I thought that even "U" needs to have some record size associated with it at open time (compiled)? If so, it won't work as I don't know the size at compile time; (b) this probably doesn't help towards doing the same for output files (or am I wrong?), so the other options might do more for me in the long run.

As for #2, I'd be willing to take that path if I *knew* it would work and someone could tell me which data area fields would need to be changed. I'm comfortable navigating MVS data areas (did quite a bit of it in assembler, though not in the past 20+ years). If this approach would work for my output files as well, I'd be thrilled!

As for #3, similar to #2, although Assembler is a bit harder to maintain for me (there are probably not more than two of us in our shop of 40 people that know assembler at all), and I've never done any linking of Cobol to assembler.

I am still hoping that someone has sample code that does this (or something similar to be modified) for any of the above three approaches.

Thanks again!!
 
All

I will reiterate the solution I implemented...

1. In FD only had RECORD CONTAINS 0 and RECORDING MODE IS F.
2. Set the 01 PIC Clause in the FD to the maximum LRECL.
3. Added the LRECL in the JCL Job that executed the Program. This was the only "downside" to the solution, since the Cobol OPEN Statement needs to know the size of the record.
4. Included the LRECL in another file. The Program read this file, and used it in the MOVE statement.

The MOVE statement is set up as...

MOVE IN-REC(1:FILE-LRECL) TO IN-AREA(1:FILE-LRECL)

Hope that helps.

 
rasanders -- thanks for the added info. What you outlined is what I have done for Fixed (F) records, and it works well (actually, I used other posted code to get the actual LRECL from the MVS data areas, so that isn't needed from the user parms).

My problem (now) is that I can't do the same for Variable (V) files -- it appears (unless I'm messing something else up) that Cobol/MVS is validating that the maximum LRECL defined to Cobol agrees with the file's real LRECL.

Perhaps I just can't figure out how to define to Cobol a V field that has no length (in the F case, that is what is effectively being done). So, once it HAS a length, then at OPEN, the system says it must match exactly the LRECL of the file.

Does this make sense, or am I missing something (which is likely!) ??

Craig
 
For Variable Block Files, I have a separate Program that handles the file/record length in the same manner as detailed in my earlier post.

The only difference is in the FD.

In the FD I have...

BLOCK CONTAINS 0
RECORD IS VARYING FROM 1 TO 5000
DEPENDING ON WS-REC-LEN.

Then, define the field...

WS-REC-LEN PIC 9(4) COMP.

That works for me.
 
rsanders -- While I have changed the code many times to try a combination that works, I *believe* that I did exactly what you note, but it didn't then allow an input file to be LRECL 3000 (for example) -- the open failed with mismatch on the LRECL. Does your implementation allow the input file to be other than LRECL 5000 (5004, with the header)? If so, I need to try it again. Also, could you tell me what the 01 definition looks like in your example?

I am hopeful that you have it working, as it would seem as perfect solution worthy of stars!

thanks, Craig
 
Craig

Yes, VB files of less than 5000 are used.

The key, I think, is the fact that in the JCL you must
include the LRECL, such as DCB=(RECVM=VB,LRECL=3004).

Try that.
 
rasanders -- I tried to follow your example and used the following FD and JCL:

Select FD-InA-V Assign to INA Status IO-Status.
:
:
FD FD-InA-V
Recording Mode is V
Block Contains 0
Record Varying 1 to 5000 Depending on InA-V-Rec-Len.
01 InA-V-Rec.
05 Filler Occurs 1 to 5000
Depending on InA-V-Rec-Len Pic X(01).
:
:
//INA DD DSN=LBCT.IBM.SFILE1,
// DCB=(RECFM=VB,LRECL=4004),
// DISP=SHR


When run, this produced the following error at OPEN:

IGZ0201W A file attribute mismatch was detected. File FD-INA-V in program CCMATCH had a record length of 5004 and the file specified in the ASSIGN clause had a record length of 4004.
{btw, the OPEN status is 39}

As yours is working (I assume on MVS system), can you please paste your exact FD and 01 and DD statement?

Thanks, Craig
 
!!! ATTENTION rasanders !!!

You were right!! After thinking about it more, I was wondering why you thought that adding the DCB=LRECL to the DD statement was necessary -- after all, it was giving it the same LRECL that the file really had (your example used the 3004 size, which is smaller than the example FD had it). Then it hit me that perhaps you meant the DD LRECL to specify the LARGER size (the one that matched the FD) ...

I tried it and IT WORKS!!!

MANY, MANY THANKS (and STARS) .... Craig
 
OK, I'm ALMOST there --- I have a strange situation that I can't figure out. I have found that I can set the FD up to, but not exceeding, a record length of 9992. Anything within that range allows the JCL DD to point to a V file that is <= the record length and use a "DCB=(LRECL=9996)" to override it. Doing so, processing works fine.

However, if the program wants to establish a larger maximum record size (ie, greater than 9992), then it never allows smaller records, even with the DCB override (of course, it will allow a matching file). AND, it gives a status code of 90, and that doesn't make any sense (seems to be for VSAM files, but this is a regular QSAM).

While a maximum LRECL of 9992 is quite good (98% of all cases), I'd like to be able to cover the other 2% of cases as well.

What is magical about 9992 (or 9996, if you consider the V header) that one can't use LRECL override on the DD effectively?

Thanks, Craig
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top