23. Binäre Dateien
In DELPHI bzw. PASCAL haben wir es im Wesentlichen mit drei Arten von Dateien zu tun:
Text-Dateien
Auf ihre Daten greift man am Besten mit den Methoden LoadFromFile bzw. SaveToFile einer Stringliste, z.B. Memo.Lines oder ListBox.Items, zu.
(siehe: 16. Der Sudoku-Assistent: Lösung, dort die Prozeduren BtnLadenClick und BtnSpeichernClick)Record-Dateien
Um auf ihre Daten zuzugreifen, wird eine Dateivariable als File of Records deklariert. Diese wird durch AssignFile mit einer Datei verknüpft und die Datensätze werden mit Read aus der Datei gelesen bzw. mit Write in die Datei geschrieben.
(siehe: 23. Record-Dateien)Binäre Dateien
Binäre Dateien sind untypisierte Dateien. Die Dateivariable wird daher nur als File ohne Datentyp deklariert, die Verknüpfung der Dateivariablen mit einer Datei erfolgt wie bei den Record-Dateien durch AssignFile.
Gelesen und geschrieben wird blockweise mit BlockRead und BlockWrite. Dazu muss vorher ein Buffer, d.h. ein array of byte deklariert werden.
Die Größe der Datenblöcke wird als zweiter Parameter bei Reset und Rewrite angegeben. Bei BlockRead wird angegeben, wie viele Blöcke in den Buffer gelesen werden sollen. Ein vierter, optionaler Parameter gibt an, wie viele Blöcke tatsächlich gelesen wurden.AssignFile(Dateivariable,Dateiname) Verbindet eine Datei mit der im Programm deklarierten Dateivariablen Reset(Dateivariable, Blockgröße) Öffnet eine bestehende Datei Rewrite(Dateivariable, Blockgröße) erzeugt eine neue Datei Seek(Dateivariable,Blocknummer) Setzt den Dateizeiger auf einen bestimmten Datenblock BlockRead(Dateivariable, Buffer, n1, [n2]) Liest n1 Datenblöcke aus der Datei in den Buffer BlockWrite(Dateivariable, Buffer, n1, [n2]) Schreibt n1 Datenblöcke aus dem Buffer in die Datei Truncate(Dateivariable) Schneidet alle folgenden Datenblöcke ab CloseFile(Dateivariable) Schließt eine Datei FileSize(Dateivariable) Liefert die Anzahl der Datenblöcke in einer Datei FilePos(Dateivariable) Liefert die Nummer des aktuellen Datenblocks Eof(Dateivariable) Ist True wenn das Dateiende erreicht ist FileExist(Dateiname) Ist True wenn die Datei vorhanden ist Beispiel: FileCopy
Mit der folgenden Prozedur wird eine beliebige Datei byteweise (Blockgröße=1) eingelesen und eine Kopie davon wieder gespeichert.
procedure TForm1.FileCopy(const InputFilename, OutputFilename: string); var InputFile, OutputFile: File; AnzGelesen, AnzGeschr : Integer; Buffer: array[1..2048] of Byte; begin AssignFile(InputFile, InputFilename); Reset(InputFile, 1); AssignFile(OutputFile, OutputFilename); Rewrite(OutputFile, 1); repeat BlockRead (InputFile, Buffer, SizeOf(Buffer), AnzGelesen); BlockWrite(OutputFile, Buffer, AnzGelesen, AnzGeschr); until (AnzGelesen = 0) or (AnzGelesen <> AnzGeschr); CloseFile(InputFile); CloseFile(OutputFile); end;
procedure TForm1.Button3Click(Sender: TObject); begin FileCopy(Edit1.Text,Edit2.Text); end;
Beispiel: HexView
Als untypisierte Dateien lassen sich alle beliebigen Dateien laden. Eine gängige Methode ist die gemischte Darstellung als Hexadezimalzahlen und ASCII-Text.
Meistens kann man an den ersten Bytes einer Datei, dem sog. Header, den Dateityp ablesen. Ein HexViewer ist schnell geschrieben.procedure TForm1.btnOpenClick(Sender: TObject); var datei: File; b: TBuffer; n:integer; begin Memo1.Font.Name := 'Courier New'; Memo1.Clear; if OpenDialog1.Execute then begin Edit1.Text := OpenDialog1.Filename; AssignFile(datei,OpenDialog1.Filename); Reset(datei,1); // Blockgröße = 1 Byte repeat BlockRead(datei, b, SizeOf(b), n); Memo1.Lines.Add(BufferToLine(b,n)); until eof(datei); end; end; function TForm1.BufferToLine(b:TBuffer; n:integer):string; var i:integer; s1,s2:string; begin s1 := ''; // String aus Hexadezimalzahlen s2 := ''; // String aus ASCII-Zeichen for i := 1 to n do begin s1 := s1 + Format('%2.2x ', [ b[i] ]); if b[i]>31 then s2 := s2 + char(b[i]) else s2 := s2 + '.'; end; result:= Format('%-96s %-32s', [s1,s2]); end;
Die Zeichenkombination 0D 0A, die wiederholt vorkommt, besteht aus den beiden Steuerzeichen CR (Carriage Return) und LF (Line Feed), die einen Zeilenumbruch bewirken.
© 2009 : Bernd Schultheiss
Einführung in das Programmieren mit DELPHI
