Agenda für heute, 9. Juni, 2005 • Direkte Filezugriffe • Textfiles • Bitmap-Dateien • Datentypen: Mengen Direkte Filezugriffe Das Problem sequentieller Dateien: Will man die k-te Filekomponente einer sequentiellen Datei lesen, dann müssen zuerst alle k-1 vorangehenden Filekomponenten gelesen werden. Schreiben ist nur am Ende der Datei möglich. Die Lösung: In Delphi steht uns die Prozedur Seek zur Verfügung. Mit Seek kann der Positionszeiger einer Filevariablen (F) auf eine bestimmte Position (N) gesetzt werden. Die nachfolgenden Read- und Write-Operationen betreffen die entsprechende Filekompenente. procedure Seek(var F; N: Longint); Programmieren und Problemlösen 2/22 © Institut für Computational Science, ETH Zürich Direkte Filezugriffe Beispiel Wir möchten den 21. Eintrag in der Datei Messstation in die 80. Position derselben Datei schreiben: Seek(Messstation,20); Read(Messstation,MW1); Seek(Messstation,79); Write(Messstation,MW1) Um eine Datei zu vergrössern, geben Sie beim Aufruf von Seek eine Komponente hinter der letzen Komponente in der Datei an: Seek(F, FileSize(F)) Dieser Prozeduraufruf setzt den Positionszeiger ans Dateiende. FileSize kann nicht für Textdateien verwendet werden. Programmieren und Problemlösen 3/22 © Institut für Computational Science, ETH Zürich Direkte Filezugriffe Beispiel Mit Wiederholungsanweisungen können ganze Bereiche einer Datei verarbeitet werden: for i:= 100 to 200 do begin Seek(Messstation,i); Read(Messstation,MW1); { MW1 verarbeiten } end Programmieren und Problemlösen Um Zugriffsfehler zu verhindern: s:= FileSize(Messstation); Was aber, wenn die Datei nur 150 for i:= 101 to 200 do Elemente enthält? if i < s then begin Seek(Messstation,i); Read(Messstation,MW1); { MW1 verarbeiten } end 4/22 © Institut für Computational Science, ETH Zürich • Direkte Filezugriffe • Textfiles • Bitmap-Dateien • Datentypen: Mengen Eigenschaften von Textfiles • In Textfiles können Werte vom Typ Char, String, Boolean, einem Integer-Typ oder einem Real-Typ geschrieben werden. • In Textfiles geschriebene Werte eines Integer-Typs, eines Real-Typs oder vom Typ Boolean werden automatisch in die entsprechende Zeichendarstellung konvertiert. • Aus Textfiles gelesene Zeichenfolgen, die ganze oder reelle Zahlen darstellen, werden automatisch in die numerischen Werte konvertiert. Entspricht die Zahl nicht dem erwarteten Format, tritt ein E/A-Fehler auf. Programmieren und Problemlösen 5/22 © Institut für Computational Science, ETH Zürich Eigenschaften von Textfiles Beispiel var F: textfile; I: integer; B: boolean; Der Prozeduraufruf Read(F,I) liest im File F eine Zeichenfolge bis zum nächsten Leerzeichen oder End-of-line-Zeichen, interpretiert sie als ganze Zahl vom Typ Integer und speichert ihren Wert in der Variablen I. Mit der Anweisungsfolge B:= true; Write(F,B) wird am Ende des Files F das Wort 'TRUE' angefügt. Programmieren und Problemlösen 6/22 © Institut für Computational Science, ETH Zürich Eigenschaften von Textfiles Textfiles speichern lineare Folgen von Textzeichen. Sie haben zusätzlich eine Zeilenstruktur, die durch spezielle Zeichen, welche das Ende einer Zeile markieren, gegeben ist. Der Text: Programmieren mit Delphi würde wie folgt gespeichert: P r o g r a m m i e r e n m i t cr lf D e l p h i End-of-line-Zeichen End-of-file-Zeichen z.B. Ord: 13 & 10 (betriebssystemspezifisch) Programmieren und Problemlösen 7/22 © Institut für Computational Science, ETH Zürich Eigenschaften von Textfiles Weil Textfiles eine Zeilenstruktur haben, müssen End-of-line-Zeichen erkannt und auch geschrieben werden können. Pascal stellt dazu die zwei Standardprozeduren Readln und Writeln zur Verfügung. Der Prozeduraufruf: Readln(F) in dem F der Name eines Textfiles ist, ist äquivalent zu den folgenden Anweisungen: while not Eoln(F) do Read(F); Read(F) Die Prozedur Readln liest eine Zeile Text und "springt" dann an den Anfang der nächsten Zeile der Datei. Programmieren und Problemlösen 8/22 © Institut für Computational Science, ETH Zürich Eigenschaften von Textfiles Die Prozedur Writeln wird dazu verwendet, um die aktuelle Ausgabezeile zu beenden und eine neue zu beginnen. Der Prozeduraufruf: Writeln(F, P) in dem F der Bezeichner eines Textfiles und P der Bezeichner einer Variablen ist, ist äquivalent zu den folgenden Anweisungen: Write(F, P); Writeln(F) Das nächste Write scheibt das erste Zeichen in die nächste Zeile der Datei. Textfiles können mit rewrite(F) oder mit append(F) geöffnet werden. Rewrite überschreibt ab Fileanfang, append fährt am Fileende fort. Programmieren und Problemlösen 9/22 © Institut für Computational Science, ETH Zürich • Direkte Filezugriffe • Textfiles • Bitmap-Dateien • Datentypen: Mengen Bitmap-Dateien BMP-Dateien bestehen aus drei Teilen: dem Dateikopf, dem Informationsblock und den Bilddaten. Dateikopf (BITMAPFILEHEADER) Informationsblock (BITMAPINFO): Bitmap-Eigenschaften Die Bilddaten werden zeilenweise gespeichert. In der Regel beginnen die Bilddaten mit der letzten und enden mit der ersten Bildzeile. 14 Byte 40 Byte (BITMAPINFOHEADER) Eventuell: Farbmasken Eventuell: Farbtabelle Eventuell: Ungenutzter Platz Bilddaten Eventuell: Ungenutzter Platz Programmieren und Problemlösen 10/22 © Institut für Computational Science, ETH Zürich Bitmap-Dateien Typendeklaration für Filevariable um Dateikopf und Informationsblock einer Bitmap-Datei einzulesen. Programmieren und Problemlösen bmpheader = packed record {----- fileinfo --------} bfType: word; bfSize: longint; bfReservde1: word; bfReserved2: word; bfOffBits: longint; {----- Bildinfo --------} biSize: longint; biWidth: longint; biHeight: longint; biPlanes: word; biBitCount: word; biCompress: longint; biSizeImage: longint; biXPPM: longint; biYPPM: longint; biClrUsed: longint; biClrImport: longint; end; 11/22 © Institut für Computational Science, ETH Zürich Bitmap-File von Übung 6 selber einlesen var bildheader: file of bmpheader; bh: bmpheader; binfo: file of byte; i: integer; b:byte; begin AssignFile(bildheader,'Bild1.bmp'); Reset(bildheader); read(bildheader,bh); CloseFile(bildheader); AssignFile(binfo,'Bild1.bmp'); Reset(binfo) end; for i:= 1 to bh.bfOffBits do Read(binfo,b); {fileheader überspringen} {ab hier Bilddaten verarbeiten} Programmieren und Problemlösen 12/22 © Institut für Computational Science, ETH Zürich Bitmap-File von Übung 6 selber einlesen (Fortsetzung) var bl, gr, rot: byte; x, y, i: cardinal; for y:= bh.biHeight-1 downto 0 do begin for x:= 0 to bh.biWidth-1 do begin Read(binfo,bl); Read(binfo,gr); Read(fi1,rot); Image1.Canvas.pixels[x,y]:= 65536*bl+256*gr+rot; end; for i:= 1 to bh.biWidth mod 4 do Read(binfo,rot) {die Null-Einträge am Ende der Zeile überspringen} end; Programmieren und Problemlösen 13/22 © Institut für Computational Science, ETH Zürich Standardprozeduren und -funktionen für Files AssignFile Weist einer Dateivariablen den Namen einer externen Datei zu. CloseFile Schliesst eine geöffnete Datei. Eof Prüft, ob das Ende der Datei erreicht ist. Erase Löscht eine externe Datei. FilePos Liefert die aktuelle Position innerhalb einer Datei. FileSize Liefert die aktuelle Grösse einer Datei. GetDir Ermittelt das aktuelle Verzeichnis eines Laufwerks. IOResult Liefert den Status der zuletzt durchgeführten Ein-/Ausgabe-Operation. MkDir Erzeugt ein Unterverzeichnis. Rename Benennt eine externe Datei um. Reset Öffnet eine existierende Datei. Rewrite Erzeugt und öffnet eine neue Datei. RmDir Löscht ein leeres Unterverzeichnis. Seek Bewegt den Positionszeiger zur angegebenen Filekomponente. TruncateSchneidet eine Datei an der aktuellen Position ab. Programmieren und Problemlösen 14/22 © Institut für Computational Science, ETH Zürich Standardprozeduren und -funktionen für Files Append Eoln Flush Read Readln SeekEof SeekEoln SetTextBuf Write Writeln Öffnet eine existierende Datei für das Anhängen weiterer Daten. Prüft, ob das Zeilenende in einer Textdatei erreicht ist. Leert den Puffer einer Textdatei, die für die Ausgabe geöffnet wurde. Bei typisierten Dateien: liest eine oder mehrere Komponenten in eine Variable. Bei Textdateien: liest einen oder mehrere Werte in eine oder mehrere Variablen. Führt einen Aufruf von Read aus und springt dann zum Anfang der nächsten Zeile der Datei. Liefert den Dateiendestatus einer Datei (EOF) zurück. Liefert den Zeilenendestatus einer Datei (EOLN) zurück. Weist einer Textdatei einen Ein-/Ausgabepuffer zu. Bei typisierten Dateien: Schreibt eine Variable in eine Dateikomponente. Bei Textdateien: Schreibt einen oder mehrere Werte in die Datei. Ruft die Prozedur Write auf und schreibt dann einen Zeilenvorschub in die Datei. Programmieren und Problemlösen 15/22 © Institut für Computational Science, ETH Zürich • Direkte Filezugriffe • Textfiles • Bitmap-Dateien • Datentypen: Mengen Mengentypen Jeder Datentyp definiert eine Menge von Werten. Im Falle des Mengentyps ist es die Menge aller möglichen Mengen, die aus den Elementen eines gegebenen Basistyps bestehen. Beispiel Type Aufzählungstyp Farbe = (rot, gruen, blau); S = set of Farbe; Basistyp (max. 256 Elemente) Programmieren und Problemlösen 16/22 © Institut für Computational Science, ETH Zürich Mengentypen: Eigenschaften Die Werte des Typs S sind die Mengen: [], [rot], [gruen], [blau], [rot, gruen], [rot, blau], [gruen, blau], [rot, gruen, blau] • Hat der Basistyp n unterschiedliche Werte, dann besitzt ihr Mengentyp 2n Werte. • Die Basis eines Mengentyps muss ein Ordinaltyp sein. (Aufzählungs- oder Unterbereichstyp) • Die Ordinalwerte der oberen und unteren Grenzen des Basistyps müssen im Bereich 0..255 liegen. Programmieren und Problemlösen 17/22 © Institut für Computational Science, ETH Zürich Mengentypen: Operationen Vereinigung + [rot] + [gruen] Durchschnitt ⇨ [rot, gruen] * [rot, gruen] * [gruen, blau] Differenz ⇨ [gruen] – [rot, gruen, blau] – [gruen] ⇨ [rot, blau] Element in (Mengenzugehörigkeit) [rot] in [rot, gruen] Programmieren und Problemlösen ⇨ TRUE 18/22 © Institut für Computational Science, ETH Zürich Mengentypen: Operationen Vergleich = Gleichheit <> Ungleichheit <= Teilmenge >= Obermenge [rot] [rot] [rot] [rot] = [rot, blau] ⇨ FALSE <> [rot, blau] ⇨ TRUE <= [rot, blau] ⇨ TRUE >= [rot, blau] ⇨ FALSE Programmieren und Problemlösen 19/22 © Institut für Computational Science, ETH Zürich Mengentypen: Anwendungsbeispiele Vergleichsoperationen werden durch den Mengentyp vereinfacht: var ch: char; ('0' <= ch) and (ch <= '9') ist wahr, wenn ch eine Ziffer darstellt. Der Mengentyp erlaubt einen bündigeren, besser lesbaren Ausdruck: ch in ['0'..'9'] Oft müssen beim Lesen einer Datei bestimmte Werte übersprungen werden. Die Anweisung: while ch in [' ',',','.',';',':'] do read(F,ch); "springt" über Leerzeichen und Satzzeichen in der File "F". Programmieren und Problemlösen 20/22 © Institut für Computational Science, ETH Zürich Mengentypen: Anwendungsbeispiele Das Kombinieren verschiedener Objekte wird durch den Mengentyp vereinfacht: type Zutaten = (Aepfel, Erdbeeren, Bananen, Nuesse, Icecream, Schokolade, Rahm, Zucker); Dessert = set of Zutaten; var Bananensplit, Strudel, Bananensplit_plus: Dessert; Bananensplit:= [Bananen, Icecream, Schokolade]; Bananensplit_plus:= Bananensplit + [Rahm]; Programmieren und Problemlösen 21/22 © Institut für Computational Science, ETH Zürich Mengentypen: Anwendungsbeispiele Test auf Mengenzugehörigkeit: var Rahmschlagen: boolean; Rahmschlagen:= Rahm in Bananensplit; False Rahmschlagen:= Rahm in Bananensplit_plus; True Programmieren und Problemlösen 22/22 © Institut für Computational Science, ETH Zürich