Getting Started with IBM i RPG: Files and Tables

Welcome to the world of RPG file handling, where your programs stop being lonely loops and start talking to the database. In this lesson, we’ll explore how to define, read, write, and update files in RPGLE, using both externally-described and program-described formats. 

Whether you're working with display files, printer files, or classic DISK-based tables, this chapter will give you the tools to make your RPG code data-aware and interactive.

Declaring Files with DCL-F

Every file in RPG starts with a DCL-F statement. This is your way of telling the compiler, “Hey, I’m going to use this file.” The syntax looks like this:

dcl-f filename [device-type] [keywords];

Device types include DISK, PRINTER, and WORKSTN. If you use a device keyword, it must be the first keyword after the file name.

A Simple RPGLE Read Example

Let’s create a file and read its contents. Run this command to generate a test file:

DSPOBJD OBJ(QGPL/QRPG*) OBJTYPE(*FILE) OUTPUT(*OUTFILE) OUTFILE(MYLIB/RPGTESTF)

Replace MYLIB with your own library name. Then, compile and run this RPGLE snippet:

dcl-f rpgtestf usropn extdesc('MYLIB/RPGTESTF') extfile(*extdesc);

open rpgtestf;
read rpgtestf;

dow not %eof;
  dsply ODOBNM;
  read rpgtestf;
enddo;

close rpgtestf;

return;

Make sure to compile with DBGVIEW(*ALL) or DBGVIEW(*LIST) so you can debug with listing view and see where ODOBNM comes from.

Debugging Insights

Using RDI or STRDBG, switch to the Listing View to see the compiler-generated input specs. You’ll notice breakpoints only hit fields you actually use—like ODOBNM. That’s RPG optimization in action.

Externally-Described vs Program-Described Files

  • Externally-described: RPG pulls the field layout from the file itself.
  • Program-described: You define the layout manually in your code.

Example of a program-described printer file:

dcl-c QPRINT_LEN 132;
dcl-f qprint printer(QPRINT_LEN);
dcl-ds qprint_ds len(QPRINT_LEN) end-ds;

qprint_ds = 'Hello';
write qprint qprint_ds;

qprint_ds = 'world';
write qprint qprint_ds;

*inlr = *on;

After running, check your spool files for a QPRINT output with two lines: “Hello” and “world.”

Implicit Open and Close

You can let RPG handle file opening and closing automatically:

dcl-f rpgtestf;

read rpgtestf;
dow not %eof;
  dsply ODOBNM;
  read rpgtestf;
enddo;

*inlr = '1';

Just remember: RPG only closes files when *INLR is set. Without it, your program might loop endlessly or leave files open across calls.

Writing and Updating Records

Use the USAGE keyword to control file access:

  • *INPUT (default)
  • *OUTPUT
  • *UPDATE
  • *OUTPUT:*UPDATE

Update example:

dcl-f rpgtestf usage(*update);

read rpgtestf;
dow not %eof;
  dsply 'new name' ODOBNM;
  update QLIDOBJD;
  read rpgtestf;
enddo;

*inlr = *on;

Write Example:

dcl-f rpgtestf usage(*output);

ODOBNM = 'ABCDE';
write QLIDOBJD;

*inlr = '1';

Use DSPFFD RPGTESTF to explore other fields you can populate before writing.

Exercises

Exercise: Remove *INLR, add RETURN. Call the program twice. Why does it only work once?
Solution: Without *INLR, the file stays open and at EOF. Add SETLL *START rpgtestf; before the loop to reset.

Exercise: Remove CLOSE, keep USROPN. Call the program twice. Why does it error the second time?
Solution: The file is still open. Add:

if not %open(rpgtestf);
  open rpgtestf;
endif;
{"email":"Email address invalid","url":"Website address invalid","required":"Required field missing"}
>