Zur Anpassung an das »Betriebssystem« des C-128 mußte die Behandlung von Files in einigen Details gegenüber den Vorgaben des report geändert werden. Diese Unterschiede wurden bereits in Kapitel 2 und bei der Vorstellung der File-Prozeduren genannt. In diesem Abschnitt wird ein zusammenfassender Überblick über das file-handling in Pascal 2.0 mit direkten Vergleichen zu anderen Implementierungen gegeben.
Im report existiert eine Unterscheidung zwischen externen und internen Dateien. Externe Dateien existieren eventuell bereits vor dem Beginn und auch nach dem Ende eines Programmes. Die statischen Filevariablen für diese Dateien werden deshalb als Programmparameter im Programmkopf genannt. In Pascal 2.0 dürfen dort nur die Standardfiles INPUT und OUTPUT aufgeführt werden, von denen zumindest das File OUTPUT deklariert werden muß. Alle anderen Files sind gemäß der Konventionen des report interne Dateien, das heißt, sie existieren nur während des Programmlaufes und andere Programme können nicht auf sie zugreifen.
Wie in den meisten Implementierungen für Microcomputer sind alle Dateien in Pascal 2.0 gemäß der obigen Terminologie externe Dateien: Sie werden auf Peripheriegeräten unter einem Filenamen gespeichert und bleiben auch nach dem Programmende erhalten. Eine Konsequenz dieser Speicherungsform ist, daß die Prozeduren RESET und REWRITE zusätzliche Parameter benötigen, um das Peripherie- gerät und den Filenamen zu spezifizieren.
Aus Gründen der Klarheit und Kompatibilität mit BASIC-Programmen werden statt RESET und REWRITE die Prozeduren OPEN und CLOSE verwendet. Dabei müssen Sie beachten, daß die im report definierte Prozedur RESET bereits den ersten Satz der Datei in die Puffervariable übernimmt, das heißt:
REWRITE(F) | entspricht OPEN(F,8,Sekundäradresse,Filename + 'S,W'); |
RESET(F) | entspricht OPEN(F,8,Sekundäradresse,Filename + 'S,W'); GET(F) |
Jedes File F wird intern mittels eines eigenen Deskriptors verwaltet, der neben der Puffervariablen (F^) Informationen über EOF(F), STATUS(F) und EOLN(F) enthält, die bei jeder Ein- und Ausgabeoperation mit dieser Filevariablen aktualisiert werden. Deshalb können Files natürlich Bestandteil anderer Datenstrukturen (Array, Record, aber nicht File) sein und auch in Prozeduren und Funktionen rekursiv definiert werden.
Files die zum Schreiben oder auch nur zum Lesen eröffnet waren, müssen mit CLOSE wieder geschlossen werden.
Hier soll noch einmal daran erinnert werden, daß GET und PUT die Daten in binärcodierter Form (gemäß der in Abschnitt 4.4.4.2 beschriebenen internen Speicherverteilung) lesen und schreiben, so daß diese Files nicht direkt ausgedruckt oder von BASIC-Programmen verwendet werden können. Falls ein Ausdruck oder eine Weiterverarbeitung erwünscht ist, können die Prozeduren READ(LN) und WRITE(LN) verwendet werden. Natürlich sind mit GET und PUT erzeugte Dateien wesentlich kompakter und schneller in der Bearbeitung, da keinerlei Konvertierung der Datenformate erforderlich ist.
Eine weitere Abweichung vom report besteht darin, daß die Puffervariable (F^) beim Lesen von einem File F nicht das nächste, sondern das zuletzt gelesene Zeichen enthält. Dies ist natürlich ein gravierender Nachteil, da damit keine Möglichkeit besteht, über die Variable F^ ein Zeichen »vorauszuschauen« (look ahead). Der Grund für diese Änderung besteht darin, daß bei der Tastatureingabe in Dialogprogrammen ein »Vorausschauen« nicht sinnvoll zu realisieren ist.
Die Funktion STATUS(F) ermöglicht eine Kontrolle über die Ergebnisse von Ein- und Ausgabeoperationen. Ausdrücklich sei darauf hingewiesen, daß STATUS(F) (anders als die Variable ST in BASIC) nicht durch Ein- oder Ausgaben auf einem anderen File als F beeinflußt werden kann.
Die Standard-Files INPUT und OUTPUT sind zwar zu Programmbeginn den Geräten Tastatur und Bildschirm zugeordnet, jedoch läßt sich diese Zuordung wie bei allen anderen Files während des Programmblaufes dynamisch mit der Prozedur OPEN ändern:
Beispiel: Um alle nachfolgenden Bildschirmausgaben am Drucker (Geräteadresse 4, Sekundäradresse 0) zu protokollieren, eignet sich der Prozeduraufruf:
OPEN(OUTPUT,4,0)
Andererseits lassen sich Eingaben, die sonst von der Tastatur erfolgen, auch von einem beliebigen Gerät lesen. Mit den folgenden Parametern werden Eingaben vom File »COMMAND.BAT« gelesen:
OPEN(INPUT,8,3,'COMMAND.BAT,S,R')
Diese Umleitungen der Aus- und Eingabe werden mit den Befehlen CLOSE(INPUT) und CLOSE(OUTPUT) rückgängig gemacht.
Im vorausgegegangenen Abschnitt wurden die Fileprozeduren in Pascal 2.0 mit ihren im report definierten Gegenstücken verglichen, so daß Sie Programme in »Standardpascal« durch kleine Änderungen an die Eigenarten des C-128 anpassen können.
In Zeitschriften und Pascalbüchern werden Sie jedoch häufiger auf Programme in TURBO-PASCAL stoßen. Diese Implementation verwendet bei Fileoperationen Routinen der Betriebsysteme CP/M bzw. MSDOS und PCDOS und weicht deshalb seinerseits vom report ab.
In TURBO-PASCAL existieren ebenfalls keine Unterschiede zwischen externen und internen Files, so daß diese auch nicht im Programmkopf aufgeführt werden. Der Filename einer Datei muß vor dem ersten Aufruf der Prozdezuren RESET und REWRITE mit ASSIGN festgelegt werden. Außerdem müssen Dateien nach der Bearbeitung mit CLOSE geschlossen werden.
In TURBO-PASCAL existiert bei einem File F keine Puffervariable F^. Daher werden die Prozduren PUT und GET durch die Prozeduren READ und WRITE ersetzt. Dabei gilt:
READ(F,X)entspricht X:= F^: GET(F);
WRITE(F,X)entsprichtF^:= X; PUT(F);
Beispiel:Die beiden folgenden Programme zeigen das Erstellen und Lesen einer sequentiellen Datei in TURBO-PASCAL und Pascal 2.0.
PROGRAM FILEDEMO(INPUT,OUTPUT); (* SCHREIBE / LESE LEERE PRODUKTDATEI IN TURBO-PASCAL *) TYPE PRODUCTRECORD = RECORD NUMBER : INTEGER; NAME : STRING[30]; INSTOCK: INTEGER; END; VAR PRODUCT : INTEGER; P : PRODUCTRECORD; PRODUCTFILE : FILE OF PRODUCTRECORD; BEGIN ASSIGN(PRODUCTFILE,'PFILE'); REWRITE(PRODUCTFILE); P.NAME:= ''; P.INSTOCK:= 0; FOR PRODUCT:= 1 TO 50 DO BEGIN P.NUMBER:= PRODUCT; WRITE(PRODUCTFILE,P); END; CLOSE(PRODUCTFILE); RESET(PRDUCTFILE); WHILE NOT EOF(PRODUCTFILE) DO BEGIN READ(PRODUCTFILE,P); WITH P DO WRITELN(NUMBER:5,NAME:20,INSTOCK:8); END; CLOSE(PRODUCTFILE); END. PROGRAM FILEDEMO(INPUT,OUTPUT); (* SCHREIBE / LESE LEERE PRODUKTDATEI IN PASCAL 2.0 *) TYPE PRODUCTRECORD = RECORD NUMBER : INTEGER; NAME : STRING[30]; INSTOCK: INTEGER; END; VAR PRODUCT : INTEGER; PRODUCTFILE : FILE OF PRODUCTRECORD; BEGIN OPEN(PRODUCTFILE,8,3,'PFILE,SEQ,WRITE'); PRODUCTFILE^.NAME:= ''; PRODUCTFILE^.INSTOCK:= 0; FOR PRODUCT:= 1 TO 50 DO BEGIN PRODUCTFILE^.NUMBER:= PRODUCT; PUT(PRODUCTFILE); END; CLOSE(PRODUCTFILE); OPEN(PRDUCTFILE,8,3,'PFILE,SEQ,READ'); GET(PRODUCTFILE); WHILE NOT EOF(PRODUCTFILE) DO BEGIN WITH PRODUCTFILE^ DO WRITELN(NUMBER:5,NAME:20,INSTOCK:8); GET(PRODUCTFILE); END; CLOSE(PRODUCTFILE); END.
In Pascal 2.0 kann also die Variable P entfallen, da die auszugebenden und einzulesenden Daten direkt in der Puffervariablen PRODUCTFILE^ vorliegen. Außerdem wurden die ASSIGN, RESET und REWRITE-Prozeduren durch OPEN-Prozeduren ersetzt. Durch die Wahl der Geräteadresse, des Filetyps und des Filenamens in Pascal 2.0 werden die Daten ebenfalls unter dem Namen »PFILE« auf Diskette gespeichert.
Schließlich sollten Sie noch beachten, daß direkt nach dem Eröffnen der Datei PRODUCTFILE zum Lesen die Operation GET(PRODUCTFILE) ausgeführt wird, damit die Puffervariable bereits den ersten Record des Files enthält.