Fixed length records

Revision as of 00:59, 14 October 2018 by rosettacode>Btiffin (Fixed length records)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

Fixed length read/write

Fixed length records is a draft programming task. It is not yet considered ready to be promoted as a complete task, for reasons that should be found in its talk page.

Before terminals, computers commonly used punch card readers or paper tape input.

A common format before these devices were superseded by terminal technology was based on the Hollerith code, Hollerith code.

These input devices handled 80 columns per card and had a limited character set, encoded by punching holes in one or more rows of the card.

These devices assumed/demanded a fixed line width of 80 chracters, newlines were not required (and could not even be encoded in some systems).

Task

Write a program to read 80 column fixed length records (no newlines) and then write out the reverse of each line as fixed length 80 column records.

Samples here use printable characters, but that is not a given with fixed lenth data. Filenames used are sample.txt, infile.dat, outfile.dat.

Note: There are no newlines, inputs and outputs are fixed at 80 columns, no more, no less, space padded. Fixed length data is 8 bit complete. NUL bytes of zero are allowed.

These fixed length formats are still in wide use on mainframes, with JCL and with COBOL (which commonly use EBCDIC encoding and not ASCII). Most of the large players in day to day financial transactions know all about fixed length records and the expression logical record length.

Sample data

To create the sample input file, use an editor that supports fixed length records or use a conversion utility. For instance, most GNU/Linux versions of

dd

support blocking and unblocking records with a conversion byte size.

Line 1...1.........2.........3.........4.........5.........6.........7.........8
Line 2
Line 3
Line 4

Line 6
Line 7
     Indented line 8............................................................
Line 9                                                                 RT MARGIN


prompt$ dd if=sample.txt of=infile.dat cbs=80 conv=block

will create a fixed length record file of 80 bytes given newline delimited text input.

prompt$ dd if=infile.dat cbs=80 conv=unblock

will display a file with 80 byte logical record lengths to standard out as standard text with newlines.

Bonus round

Forth systems often include BLOCK words. A block is 1024 bytes. Source code was stored as 16 lines of 64 characters each (again, no newlines).

Write a program to convert a block file to text (using newlines). Trailing spaces should be excluded from the output. Also demonstrate how to convert from a normal text file to block form. All lines either truncated or padded to 64 characters with no newlines. The last block filled to be exactly 1024 characters by adding blanks if needed. Assume a full range of 8 bit byte values for each character (in ASCII when encoding blank spaces).

The COBOL example uses forth.txt and forth.blk filenames.

COBOL

<lang cobol> *> Rosetta Code, fixed length records

     *> Tectonics:
     *>   cobc -xj lrecl80.cob
      identification division.
      program-id. lrecl80.
      environment division.
      configuration section.
      repository.
          function all intrinsic.
      input-output section.
      file-control.
          select infile
              assign to infile-name
              organization is sequential
              file status is infile-status
          .
          select outfile
              assign to outfile-name
              organization is sequential
              file status is outfile-status
          .
      data division.
      file section.
      fd infile.
          01 input-text pic x(80).
      fd outfile.
          01 output-text pic x(80).
      working-storage section.
      01 infile-name.
         05 value "infile.dat".
      01 infile-status pic xx.
         88 ok-input value '00'.
         88 eof-input value '10'.
      01 outfile-name.
         05 value "outfile.dat".
      01 outfile-status pic xx.
         88 ok-output value '00'.
      procedure division.
      open input infile
      if not ok-input then
          display "error opening input " infile-name upon syserr
          goback
      end-if
      open output outfile
      if not ok-output
          display "error opening output " outfile-name upon syserr
          goback
      end-if
     *> read lrecl 80 and write the reverse as lrecl 80
      read infile
      perform until not ok-input
          move function reverse(input-text) to output-text
          write output-text
          if not ok-output then
              display "error writing: " output-text upon syserr
          end-if
          read infile
      end-perform
      close infile outfile
     *> from fixed length to normal text, outfile is now the input file
      open input outfile
      if not ok-output then
          display "error opening input " outfile-name upon syserr
          goback
      end-if
      read outfile
      perform until not ok-output
          display function trim(output-text trailing)
          read outfile
      end-perform
      close outfile
      goback.
      end program lrecl80.</lang>

Given a starting file sample.txt of

Line 1...1.........2.........3.........4.........5.........6.........7.........8
Line 2
Line 3
Line 4

Line 6
Line 7
     Indented line 8............................................................
Line 9                                                                 RT MARGIN

And a setup pass of

prompt$ dd if=sample.txt of=infile.dat cbs=80 conv=block
Output:
prompt$ cobc -xj fixed-length.cob
8.........7.........6.........5.........4.........3.........2.........1...1 eniL
                                                                          2 eniL
                                                                          3 eniL
                                                                          4 eniL

                                                                          6 eniL
                                                                          7 eniL
..............................................................8 enil fo tuO
NIGRAM TR                                                                 9 eniL
prompt$ file outfile.dat
outfile.dat: ASCII text, with very long lines, with no line terminators

blocks

Demonstrate text to Forth source block form.

<lang cobol> *> Rosetta Code fixed length records, text to Forth block

      identification division.
      program-id. blocking.
      environment division.
      configuration section.
      repository.
          function all intrinsic.
      input-output section.
      file-control.
          select infile
              assign to infile-name
              organization is line sequential
              file status is infile-status
          .
          select outfile
              assign to outfile-name
              organization is sequential
              file status is outfile-status
          .
      data division.
      file section.
      fd infile.
          01 input-text pic x(64).
      fd outfile.
          01 output-text pic x(64).
      working-storage section.
      01 infile-name.
         05 value "forth.txt".
      01 infile-status pic xx.
         88 ok-input value '00'.
         88 eof-input value '10'.
      01 outfile-name.
         05 value "forth.blk".
      01 outfile-status pic xx.
         88 ok-output value '00'.
      procedure division.
     *> read a line, padded to or truncated at 64 as defined in FD
      open input infile
      if not ok-input then
          display "error opening input " infile-name upon syserr
          goback
      end-if
      open output outfile
      if not ok-output
          display "error opening output " outfile-name upon syserr
          goback
      end-if
      move 0 to tally
      read infile
      perform until not ok-input
          move input-text to output-text
          write output-text
          if not ok-output then
              display "error writing: " output-text upon syserr
          end-if
          add 1 to tally
          if tally > 15 then move 0 to tally end-if
          read infile
      end-perform
     *> Output up to next 1024 byte boundary
      if tally > 0 then
          compute tally = 16 - tally
          move spaces to output-text
          perform tally times
              write output-text
              if not ok-output then
                  display "error writing: " output-text upon syserr
              end-if
          end-perform
      end-if
      close infile outfile
      goback.
      end program blocking.</lang>

Demonstrate Forth source block to text form.

<lang cobol> *> Rosetta Code fixed length records, Forth blocks to text.

      identification division.
      program-id. unblocking.
      environment division.
      configuration section.
      repository.
          function all intrinsic.
      input-output section.
      file-control.
          select infile
              assign to infile-name
              organization is sequential
              file status is infile-status
          .
          select outfile
              assign to outfile-name
              organization is line sequential
              file status is outfile-status
          .
      data division.
      file section.
      fd infile.
          01 input-text pic x(64).
      fd outfile.
          01 output-text pic x(64).
      working-storage section.
      01 infile-name.
         05 value "forth.blk".
      01 infile-status pic xx.
         88 ok-input value '00'.
         88 eof-input value '10'.
      01 outfile-name.
         05 value "forth.txt".
      01 outfile-status pic xx.
         88 ok-output value '00'.
      procedure division.
      open input infile
      if not ok-input then
          display "error opening input " trim(infile-name) upon syserr
          goback
      end-if
      open output outfile
      if not ok-output
          display "error opening write " trim(outfile-name) upon syserr
          goback
      end-if
     *> read a fixed length line, 64 characters
      read infile
      perform until not ok-input
          move trim(input-text) to output-text
          write output-text
          if not ok-output then
              display "error writing: " output-text upon syserr
          end-if
          read infile
      end-perform
      close infile outfile
      goback.
      end program unblocking.</lang>