Mit Streams Daten lesen und schreiben
Nach oben zu Streams verwenden
Alle Stream-Klassen besitzen verschiedene gemeinsame Methoden zum Lesen und Schreiben von Daten. Diese Methoden werden unterschieden, abhängig davon, ob sie:
- die Anzahl gelesener bzw. geschriebener Bytes zurückgeben.
- erfordern, dass die Anzahl der Bytes bekannt sein muss.
- bei Fehlern eine Exception auslösen.
Inhaltsverzeichnis
Stream-Methoden zum Lesen und Schreiben
Die Read-Methode liest, beginnend bei der aktuellen Position, die angegebene Anzahl von Bytes aus dem Stream in einen Puffer ein. Read korrigiert dann die aktuelle Position nach Maßgabe der tatsächlich übertragenen Bytes. Der Prototyp für Read lautet:
C++:
virtual int __fastcall Read(void *Buffer, int Count);
Delphi:
function Read(var Buffer; Count: Longint): Longint;
Read ist hilfreich, wenn die Anzahl der Bytes in der Datei nicht bekannt ist. Read gibt die Anzahl der tatsächlich übertragenen Bytes zurück. Dieser Wert kann kleiner als Count sein, wenn der Stream ab der aktuellen Position nicht genügend Zeichen enthält.
Write ist eine Funktion, die eine bestimmte Anzahl von Bytes (Count) aus einem Puffer (Buffer) in den Stream schreibt, beginnend an der aktuellen Position. Der Prototyp für Write lautet:
C++:
virtual int __fastcall Write(const void *Buffer, int Count);
Delphi:
function Write(const Buffer; Count: Longint): Longint;
Nach dem Schreiben in die Datei setzt die Methode Write die aktuelle Position um die Anzahl von Bytes vor, die geschrieben wurden. Zurückgegeben wird die Anzahl der tatsächlich geschriebenen Bytes, die kleiner als Count sein kann, wenn der Puffer weniger als Count Bytes enthält oder der Stream nicht mehr Bytes aufnehmen kann.
Die Gegenstücke heißen ReadBuffer und WriteBuffer, die im Gegensatz zu Read und Write nicht die Anzahl der gelesenen bzw. geschriebenen Bytes zurückgeben. Diese Methoden sind hilfreich, wenn die Anzahl von Bytes bekannt und erforderlich ist, z.B. beim Lesen von Strukturen. ReadBuffer und WriteBuffer lösen eine Exception (EReadError bzw. EWriteError) aus, wenn die Byte-Anzahl nicht mit der angegebenen übereinstimmt. Die Methoden Read und Write lösen in diesem Fall keine Exception aus. Die Prototypen für ReadBuffer und WriteBuffer lauten folgendermaßen:
C++:
virtual int __fastcall ReadBuffer(void *Buffer, int Count);
virtual int __fastcall WriteBuffer(const void *Buffer, int Count);
Delphi:
procedure ReadBuffer(var Buffer; Count: Longint);
procedure WriteBuffer(const Buffer; Count: Longint);
Diese Methoden rufen die Methoden Read und Write auf, um die eigentlichen Lese- bzw. Schreiboperationen durchzuführen.
Komponenten lesen und schreiben
TStream definiert die speziellen Methoden ReadComponent und WriteComponent zum Lesen und Schreiben von Komponenten. Sie können diese Methoden in Ihren Anwendungen benutzen, um Komponenten und deren Eigenschaften zu speichern, wenn Sie diese zur Laufzeit erzeugen oder ändern.
Auch die IDE benutzt die Methoden ReadComponent und WriteComponent, um Komponenten in einer Formulardatei zu speichern oder sie daraus zu lesen. Dabei arbeiten die Stream-Klassen mit TFiler, TReader und TWriter.
Weitere Informationen über das Streaming-System für Komponenten finden Sie unter System.Classes.TStream, System.Classes.TFiler, System.Classes.TReader, System.Classes.TWriter und System.Classes.TComponent.
Strings lesen und schreiben
Wenn Sie einen String an eine Lese- oder Schreibfunktion übergeben, müssen Sie die zu verwendende Syntax kennen. Die Parameter Buffer der Lese- bzw. Schreibroutinen sind var- bzw. const-Parameter. Da es sich um untypisierte Parameter handelt, nimmt die Routine also die Adresse einer Variablen entgegen.
Bei der Arbeit mit Strings wird normalerweise der UnicodeString-Typ verwendet. Mit langen Strings erhalten Sie hier aber nicht das richtige Ergebnis. Lange Strings enthalten die Größe, einen Referenzzähler und einen Zeiger auf die Zeichen im String. Das Dereferenzieren eines langen Strings bezieht sich deshalb nicht nur auf das Zeigerelement. Sie müssen den String in einen Pointer oder PChar umwandeln, bevor Sie ihn dereferenzieren. Beispiel:
Delphi:
procedure caststring;
var
fs: TFileStream;
const
s: string = 'Hello';
begin
fs := TFileStream.Create('temp.txt', fmCreate or fmOpenWrite);
fs.Write(s, Length(s)); // Liefert Datenmüll
fs.Write(PChar(s)^, Length(s)*SizeOf(Char)); // Das ist die richtige Methode
end;