Guru: Open Access To The Rescue
February 11, 2019 Jon Paris
Recently I came upon a couple of questions on internet lists asking for an easy method to create flat files in the IFS. Not CSV files, but rather simple text files where individual data items are in fixed character positions. Various somewhat convoluted solutions were offered to the requestors, but to me this problem shouted “Open Access!”
So, I set about quickly building an Open Access (OA) handler to perform the task. I find OA really useful for this kind of job because, once the handler is written, creating these kinds of files in the future become a trivial task, no matter the format required. Perhaps even more importantly, only the person who wrote the handler has to understand how to write to the IFS. Others in the shop only have to understand how to use what, in this case, appears to be a regular printer file.
Speaking of the “printer” file let’s take a look at it in action:
Dcl-f IFSPrinter Printer(50) Handler('IFSWRTRECH'); Dcl-F CustMast Keyed; Read CustMast; DoU %Eof(CustMast); Except IFSLine1; Read CustMast; EndDo; *InLr = *On; OIFSPrinterE IFSLine1 O Cust# 5 O Name 40 O Credit 50
This is an extract from the resulting IFS file:
00345 Joe's Skateboards 0020000 00495 Best Stuff You Can Buy 0002000 00518 Nancy Nail 0003000 01538 John Carter 0002000 08410 Terrific Toys 0003000 15392 Jane Smith 0200000 28395 Alice Sundry 0150000
This program is so simple that I won’t spend any time explaining it. All it does is to read through the Customer Master file (CUSTMAST) and outputs the fields Cust#, Name, and Credit in positions 1 – 5, 11 – 40, and 44 – 50 respectively. Changing the format of the IFS file would simply require changing the O-specs.
Instead I’ll focus on why the handler was designed the way it was. Deciding on a handler architecture is by far the hardest part of the task and requires that you have an understanding of what a handler can and cannot do. For example, from studying the sample program above, a couple of questions may have occurred to you:
- “Why did he use a program-described printer file?” and/or
- “Would this handler work for an externally described printer file?”
Yes. It will work with an externally described file. But, there’s a problem with using externally described files. OA simply passes a data buffer to the handler. Positioning the components of that data at specific points within the line is the job of the operating system’s data management routines outside the RPG program. But when I use OA those system routines are bypassed, leaving the formatting work up to the handler.
However, if I use a program-described file, I can position the data in the required locations directly through the O-specs and the buffer passed to the handler will already have the data in the specified positions when the handler gets it. Not only this, but I can also use edit codes, edit words, literals, etc. in the layout. Like the positioning information, were I using an externally described file, all of that capability would also be lost.
I could have written a file-specific handler, but the beauty of this approach is that the handler is generic, producing any format of output needed by simply changing the RPG program’s O specs. It’s ironic that in this case the best way to take advantage of OA — one of RPG’s more modern facilities — is to use the old O-specs.
As it happens, the nature of this handler is such that it will work with disk files as well as printer files. I only used a printer in my example because I have encountered situations where fixed format IFS files required multiple record layouts. e.g., Header/Detail situations. By using a “printer” such flexibility is really simple to achieve.
The Handler
I won’t describe the handler in detail since the basic mechanics are very similar to the Data Queue writer that I described in a previous Tip. If you are not familiar with OA handlers, you will need to read the article that described that handler in order to understand the code for this one. You will find the article here: Join The Queue With Open Access. That page also contains a link to the associated code bundle.
Writing OA handlers isn’t difficult but requires quite a bit of “plumbing” which can make them appear to be very complicated. That’s why I created a standard OA template program which takes care of most of the plumbing and allows me to focus just on the logic needed to make a specific handler work. In this case, that logic is primarily using C APIs to create and write to an IFS file.
I’ll cover just one detail of the handler. For simplicity, I decided to have the handler build the IFS file name from a combination of the RPG file’s file name, the date, and the current time. The result is a file name that looks like this: IFSPRINTER_2019-01-30_19.36.28.txt. In a production version of the handler I would want to be able to specify the full path and file name. This would be done by using the ability to specify a user parameter to the HANDLER keyword. Similarly I might also want to be able to specify the code page for the file and perhaps even the record delimiter character(s). I will cover how to meet these requirements in a subsequent tip.
Summary
My goal with this tip was to get you thinking about OA as a relatively simple solution to an application challenge, not to teach OA in detail and certainly not to teach IFS APIs. If you want to study this handler (or simply download it for your own use) you can download the code package here.
Open Access can be a simple solution to many application problems, and using a standard OA template dramatically reduces the time required to build handlers. You can download the latest version of my OA template program here.
Jon Paris is one of the world’s foremost experts on programming on the IBM i platform. A frequent author, forum contributor, and speaker at User Groups and technical conferences around the world, he is also an IBM Champion and a partner at Partner400 and System i Developer. He hosts the RPG & DB2 Summit twice per year with partners Susan Gantner and Paul Tuohy.
Why was CPYTOIMPF not an acceptable option?
Hi Ronnie, sorry for the delay in responding – there is a problem in getting the system to notify us when comments are posted.
To answer your question. CPYTOIMPF could not perform the task because the user’s requirement was for columnar data with no field separators. Unless it is a new feature that I am unaware of, CPYTOIMPF does not provide any mechanism to allow for that.
I should also say that I really detest CPYTOIMPF. Changes in the defaults and parameter requirements over the years have caused many of my clients no end of grief when they had non-standard requirements. Even if that were not the case, when I have the option to use an OA handler to simplify the task, why would I not use it? With CPYTOIMPF I have to write a disk file, then call the utility to copy it to the IFS, and then probably remember to clear out the disk file. Using an OA handler all I have to do is specify the handler on the disk files F-spec and then remove all the extra cope related to CPYTOIMPF.
After I published an IFS writer some years ago (http://ibmsystemsmag.com/ibmi/developer/rpg/open-access-templates/) I had many emails from people thanking me for making it so much easier to create IFS files – so I guess I’m not the only one who fels that way about CPYTOIMPF
Are the links for this code package and the OA template supposed to be the same? They download the same file.
Hi Michael, sorry for the delay in responding – there is a problem in getting the system to notify us when comments are posted.
The latest template was included in the code package and I forgot to remove the other link after I decided to include it – sorry about that.