MainframeSupports
tip uge 4/2010:

I nogen situationer har jeg behov for at genlæse en fil fra et bestemt punkt. Det er typisk, når sammenhængende data breder sig over flere records. Hidtil har jeg løst udfordringen ved at have en intern buffer, hvor jeg gemte de indlæste records. Hvis jeg så havde brug for data, jeg allerede havde læst, så fik jeg fat i dem ved hjælp af bufferen. Problemet ved denne løsning er, at bufferen typisk har en eller anden øvre grænse for, hvor stor den kan blive. Derudover skal man selv opfinde en eller anden bufferteknik.

En af mine kolleger foreslog mig i stedet at have to filer åbne i programmet mod samme dataset. Så fungerer den ene fil på sædvanlig måde, mens den anden fil fungerer som buffer. Det synes jeg er en rigtig fiks løsning, som jeg viderebringer et eksempel på her. Input til det følgende program er en fil som eksempelvis kan se således ud:

INIT A
DATA BELONGING TO A
INIT B
DATA BELONGING TO B
X IN POSITION ONE TRIGGERS DISPLAY OF ALL DATA BELONGING TO PREVIOUS INIT
MORE DATA BELONGING TO B
INIT C
DATA BELONGING TO C
AND SO ON

Og her er programmet skrevet i COBOL. Jeg har kun medtaget det mest nødvendige, så du må selv tilføje manglede divisions og sections samt foretage de nødvendige indrykninger, hvis du vil prøve det af. Hvis du hellere vil bruge PL/I, så er tricket at benytte TITLE på OPEN FILE:

input-output section.
file-control.
    select somefile assign to somefile
      file status is someStatus.
    select othrfile assign to othrfile
      file status is othrStatus.
data division.
file section.
fd  somefile
    recording mode is F.
01  somedata pic x(80).
fd  othrfile
    recording mode is F.
01  othrdata pic x(80).
working-storage section.
01  someStatus pic 9(2).
01  someCount  pic s9(9) binary.
01  othrStatus pic 9(2).
01  othrCount  pic s9(9) binary.
...
open input somefile
move 0 to someCount
open input othrfile
move 0 to othrCount
read somefile
read othrfile
perform until someStatus not = 0
  if someData(1:1) = 'I' and someCount not = othrCount
    perform until othrCount = someCount or othrStatus not = 0
      add 1 to othrCount
      read othrFile
    end-perform
  end-if
  if someData(1:1) = 'X'
    display othrData
    add 1 to othrCount
    read othrFile
    perform until othrData(1:1) = 'I' or othrStatus not = 0
      display othrData
      add 1 to othrCount
      read othrFile
    end-perform
    perform until someData(1:1) = 'I' or someStatus not = 0
      add 1 to someCount
      read someFile
    end-perform
  else
    add 1 to someCount
    read somefile
  end-if
end-perform
close somefile
close othrfile
goback
.

Det første, der falder dig i øjnene er nok, at jeg laver assign til to forskellige filer. Det er desværre nødvendigt at have to DD-navne i det tilhørende JCL for at opnå den nødvendige funktionalitet. Bemærk i øvrigt at jeg kun tester på det første tegn i input. Den vigtigste detalje i programmet er, at spole bufferfilen frem til den næste sammenhængende klump af data. Det styrer jeg ved hælp af variable someCount og otherCount. Jeg tror det kan gøres mere elegant, men jeg kunne ikke umiddelbart finde på noget smartere. Der skal sandsynligvis andre tilpasninger til afhængig af den konkrete opgave, du skal løse.

Resultatet af at afvikle programmet er følgende records på SYSOUT:

INIT B
DATA BELONGING TO B
X IN POSITION ONE TRIGGERS DISPLAY OF ALL DATA BELONGING TO PREVIOUS INIT
MORE DATA BELONGING TO B

Det tilhørende jobstep til at afvikle programmet med kan se således ud:

//MYSTEP   EXEC PGM=MYBUFPG
//STEPLIB  DD DISP=SHR,DSN=MY.LOAD.DATASET
//SYSOUT   DD SYSOUT=*
//SOMEFILE DD DISP=SHR,DSN=MY.INPUT.DATA
//OTHRFILE DD DISP=SHR,DSN=*.SOMEFILE

Jeg kunne umiddelbart ikke finde en metode, hvor jeg kunne angive input ved hjælp af en //SOMEFILE DD * og en reference til OTHRFILE. Hvis du ved, hvordan man gør det, vil jeg gerne høre om det. Bemærk i øvrigt referencen til datasetnavnet på SOMEFILE på DD-kortet til OTHRFILE, så slipper du i hvert fald for at skulle huske at rette dataset-navnet to steder.

Forrige danske tip        Last tip in english        Tip oversigten