MainframeMaster

OUTREC Statement

The OUTREC control statement reformats records after the sort or merge phase, just before they are written to SORTOUT. You use OUTREC FIELDS= or OUTREC BUILD= to define the final output layout: copy only the fields you need from the sorted record, insert blanks or constants, reorder columns, and optionally apply edit masks or format conversions. OUTREC does not change the order of records—that was already determined by the sort or merge—it only changes the content and length of each record as it is written. Use OUTREC when you need a report-style layout, column alignment, sequence numbers in the output, or a shorter or reordered record for a downstream program. This page covers OUTREC syntax, FIELDS= and BUILD=, inserting blanks (nX) and binary zeros (nZ), when to use OUTREC versus INREC, and how OUTREC determines the SORTOUT record length.

Control Statements
Progress0 of 0 lessons

What OUTREC Does

OUTREC (Output Record) runs in the output phase. After DFSORT has sorted or merged the records (and applied SUM if specified), each record is handed to OUTREC. OUTREC builds a new record from that input—copying some fields, inserting constants or padding—and that new record is what is written to the dataset allocated to SORTOUT. So OUTREC does not change how many records you have or their order; it changes the layout and length of each record in the output file.

The "input" to OUTREC is the record as it exists at output time. If you used INREC, that is the reformatted (possibly shortened) record. If you did not use INREC, it is the original SORTIN record. So when you write OUTREC FIELDS=(1,10,20,5), the positions 1–10 and 20–24 refer to that post-sort record, not the original raw input. That is important when you use both INREC and OUTREC: INREC might have produced a 50-byte record, so OUTREC positions are 1–50, not 1–80.

OUTREC FIELDS= Syntax

The common form is OUTREC FIELDS=(item1,item2,...). Each item is either a field copy, a constant, or a padding specifier. Items are placed into the output record in the order you list them. The output record length is the sum of the lengths of all items, and that is the length that must be allocated for SORTOUT (LRECL).

Field copy: (position,length)

A pair (position,length) means: copy length bytes from the record at output time, starting at byte position. Positions are 1-based. So (1,20) copies the first 20 bytes of the record that the sort produced; (50,10) copies bytes 50–59. The order in the FIELDS= list is the order in the output—so you can reorder columns by listing them in the order you want in the report.

Character and hex constants: C'...' and X'...'

You can insert fixed data that does not come from the record:

  • C'literal' — Character constant in EBCDIC. C'HELLO' inserts five bytes. C' ' is one space. Useful for labels, delimiters, or fixed text in reports.
  • X'hex' — Hexadecimal constant. X'40' is one EBCDIC space; X'C1C2C3' is the three bytes for A, B, C in EBCDIC. Useful for non-printable characters.

Blanks and binary zeros: nX and nZ

OUTREC provides shorthand for common padding:

  • nX — Insert n blank (space) characters. 1X or X is one space; 5X is five spaces. Typically n is 1 to 4095. Use nX to align columns or create margins in reports (e.g. between a key and a value).
  • nZ — Insert n binary zeros (X'00'). 1Z or Z is one byte of zero; 5Z is five bytes. Useful when you need a placeholder field (e.g. for a later program to fill) or when the downstream system expects binary zeros in certain positions.

So OUTREC FIELDS=(1,10,5X,11,20) builds: 10 bytes from positions 1–10, then 5 spaces, then 20 bytes from positions 11–30. Total length 10 + 5 + 20 = 35 bytes. SORTOUT should have LRECL=35.

OUTREC BUILD= Syntax

OUTREC BUILD= works like FIELDS=: you list items in order (field copies, constants, nX, nZ). BUILD= is often preferred in modern documentation and shops to make it clear you are "building" the output record; the behavior is the same as FIELDS=. Example:

text
1
OUTREC BUILD=(1,20,3X,21,30,C' | ',31,50)

Output: 20 bytes from 1–20, 3 spaces, 10 bytes from 21–30, the literal " | " (space, pipe, space), then 20 bytes from 31–50. Total length: 20 + 3 + 10 + 3 + 20 = 56 bytes.

Example: Report Layout with Blanks

Suppose the sorted record has: bytes 1–10 customer ID, 11–30 name, 31–38 amount (packed). You want the output to have: ID, then 5 spaces, name, then 5 spaces, then the amount field. You can write:

text
1
2
SORT FIELDS=(1,10,CH,A) OUTREC FIELDS=(1,10,5X,11,20,5X,31,8)

The output record is 10 + 5 + 20 + 5 + 8 = 48 bytes. Each field is separated by 5 spaces for readability. The sort order is unchanged; OUTREC only formats how each line looks when written.

Example: Reordering and Dropping Fields

You have an 80-byte record but only need three fields for the next step: bytes 106–109, 162–165, and 166–169. By listing only those in OUTREC, you both reorder and shorten:

text
1
2
OPTION COPY OUTREC FIELDS=(106,4,162,4,166,4)

No sort is performed (OPTION COPY). OUTREC copies three 4-byte fields into a 12-byte output record. The rest of the 80-byte input is dropped. SORTOUT must have LRECL=12.

OUTREC and SORTOUT LRECL

The record length written to SORTOUT is exactly the length of the record built by OUTREC. So you must set the SORTOUT dataset's LRECL (and RECFM, usually FB for fixed) to match. If OUTREC builds a 60-byte record, allocate SORTOUT with LRECL=60. If you get it wrong, you can get truncated data, padding, or allocation errors. To compute the length, add the lengths of every item: each (position,length) contributes length; each C'...' contributes its character count; nX and nZ contribute n; X'...' contributes half the hex digit count.

INREC vs OUTREC: When to Use Which

Use INREC when the change is for the benefit of the sort: building a sort key, shortening the record so less data is sorted, or normalizing the layout for SORT FIELDS= or INCLUDE/OMIT. Use OUTREC when the change is for the final output: report formatting, column order for a reader or downstream program, sequence numbers, edit masks, or inserting labels and blanks. If you need both—e.g. shorten in INREC for performance, then format in OUTREC for the report—use both; the sort sees the INREC record, and SORTOUT gets the OUTREC record.

Edit Masks and Conversions (Brief)

OUTREC can do more than copy and constants. You can specify edit masks (e.g. EDIT=(TTT,TTT.TT)) to format numeric fields with commas and decimal points for display. You can use conversions such as TO=PD, TO=ZD, LENGTH= to change numeric format or length. You can add sequence numbers (e.g. 1,8,ZD with a counter) so each output line gets a line number. These are covered in the OUTREC Processing and related tutorials (edit masks, numeric formatting, sequence numbers). For a first step, FIELDS= or BUILD= with (position,length), C'...', nX, and nZ is enough to build most output layouts.

Variable-Length Records and OUTREC

For variable-length (VB) output, the first 4 bytes of the record are usually the Record Descriptor Word (RDW). You typically include 1,4 as the first item in OUTREC so the RDW is copied (or built) and the output remains valid VB. Then add the data fields. Omitting or misbuilding the RDW can make the output invalid for downstream programs that expect VB.

Explain It Like I'm Five

Imagine you have already sorted your cards and they are in the right order. Now you want to write the answer on a new sheet of paper. OUTREC is the rule for how you write each line: "Write the first part from the card, then leave five spaces, then write the next part, then leave five spaces, then write the number." So the order of the lines does not change—that was the sort. OUTREC only decides what each line looks like when you write it down. If you want to leave some things out (only write three numbers from each card), OUTREC does that too. INREC is different: that happens before sorting, when you are still preparing the cards. OUTREC happens at the end, when you are writing the final list.

Exercises

  1. Write OUTREC FIELDS= to output bytes 1–15 from the sorted record, then 10 spaces, then bytes 20–35. What is the output record length?
  2. What is the difference between 5X and 5Z in OUTREC? When would you use each?
  3. You use INREC to build a 40-byte record, then SORT, then OUTREC to build a 50-byte output. What positions does OUTREC refer to—the original input or the 40-byte record? What LRECL should SORTOUT have?
  4. Write OUTREC to produce: 8-byte ID, one comma, 20-byte name, 5 spaces, 10-byte amount. Give the total length.

Quiz

Test Your Knowledge

1. When does OUTREC run in DFSORT?

  • Before the sort phase
  • During the input phase
  • After the sort/merge phase, when writing output
  • Only with INREC

2. OUTREC FIELDS=(1,10,5X,11,20) produces an output record of what length?

  • 20 bytes
  • 25 bytes
  • 30 bytes
  • 35 bytes

3. What do the positions in OUTREC FIELDS= refer to?

  • The original SORTIN record
  • The record as it is after the sort phase (or after INREC if used)
  • The SORTOUT DCB
  • The SYSIN control statements

4. You want to add a sequence number to each line of the final report. Where do you do it?

  • In INREC only
  • In OUTREC or OUTFIL build, after the sort
  • In SORT FIELDS
  • In INCLUDE

5. What does 5X in OUTREC FIELDS= mean?

  • Copy 5 bytes from input position X
  • Insert 5 blank (space) characters
  • Skip 5 bytes
  • Hex value 5X