![]() |
Stream auslesen
Hi NG.
Delphi 4 (update 3) Ich versuche gerade zu verstehen, wie ich Daten aus einem Stream auslesen kann. Dazu habe ich folgenden Beitrag gefunden, insb. ![]()
Delphi-Quellcode:
Dass es funktioniert, habe ich durch Nachbauen festgestellt. Mir fehlt es aber anscheinend an Grundlagen.
SetLength(LBuffer2, 50);
LBytes := AStream.Read(LBuffer2[1], 50); LBuffer := copy(LBuffer2, 1, LBytes); Warum muss ich für LBuffer2 die Länge vordefinieren? Im Read wird doch vorgegeben, dass ich 50 Bytes lesen will. Warum muss ich anschließend das ganze in eine zweite Variable LBuffer umkopieren? Wenn das Read weniger als 50 Bytes liefert, also LBytes, macht das schon Sinn. Aber was ist, wenn das Stream ausreichend Bytes enthält? Ihr merkt, ich bin bzgl Stream und Zeiger ein Anfänger. Ich habe mir auch schon das ![]() Klärt mich bitte auf :cry: Gruß Peter |
Re: Stream auslesen
Zitat:
Zitat:
Zitat:
|
Re: Stream auslesen
Zitat:
Wenn ich nicht mit Streams arbeite, gebe ich doch bei einer String-Variable auch nicht vorher die Länge vor, sondern setze einfach: sText := 'Abc' Zitat:
|
Re: Stream auslesen
Zitat:
|
Re: Stream auslesen
Was ist denn dann der Unterschied zwischen der Verwendung eines String auf diese Weise [sText := 'Abc'] oder wie ich es für ein Stream machen muss?
|
Re: Stream auslesen
Die Methode Read erwartet einen Zeiger auf eine Speicheradresse und wie Khabarakh schon sagt:
Zitat:
|
Re: Stream auslesen
Zitat:
Das Literal wird vom Compiler zur Compiletime ausgewertet. Es wird sozusagen eine Konstante angelegt, die Zeichenkette auf die Länge analysiert und das Literal mit genau dieser Länge erstellt. [edit] Der rote Kasten hat mich verlassen :cry: [/edit] |
Re: Stream auslesen
Zitat:
|
Re: Stream auslesen
Zitat:
|
Re: Stream auslesen
im übrigen ist folgendes effektiver:
Delphi-Quellcode:
Ich versuch das ganze auch mal zu erklären.
SetLength(LBuffer1, 50);
LBytes := AStream.Read(LBuffer1[1], 50); SetLength(LBuffer, LBytes); "AStream.Read" macht intern nicht etwa eine Zuweisung wie "a := 'abc'" sondern AStream.Read kopiert letztendlich zeischen von einer Stelle an eine andere Stelle im Speicher. Du könntest also
Delphi-Quellcode:
schreiben und damit versuchen an die Adresse "20", 50 Bytes aus dem Stream zu kopieren. Als Ergebnis wird dir dann jedoch eine Fehlermeldung wie "Zugriffsverletzung an Adresse 000020" oder so ausgegeben.
AStream.Read(Pointer(20)^, 50);
AStream.Read erwartet also einfach eine Adresse (dereferenziert) so es Daten hinschreiben kann. Als Bildlisches Beispiel. Du bestellst eine LKW-Ladung Sand uns sagst dem LKW-Faherer wo er das ganze abladen soll. Der LKW wird dann an die entsprechende stelle gefahren und kippt dort den Sand ab. Dem LKW-Fahrer ist es dabei egal ob er das ganze in einen Sandkasten ablädt der eventuell zu klein ist oder auf das Grundstück deines Nachbarn, er lädt es dort hinn wo du es sagst. Und genau so verhält es sich mit dem "Stream.Read" es lädt die Bytes an die Stelle im Speicher die du angibst. Der Vorteil ist das man bei Stream.Read jeden Variablentyp nutzen kann. Wenn es speziel für bestimmte Datentypen (String, Integer, Byte,...) eine Extra funktion gäbe würde man schnell an die grenzen stoßen da ja auch jemand neue Datentypen definieren will die natürlich auch gelesen werden sollen. Wie dir eventuell auch schon aufgefallen ist hat der erste Parameter von "Stream.Read" keinen Typ, das heißt innerhalb der Funktion kann man nicht einfach
Delphi-Quellcode:
schreiben weil Buffer kein String ist
function TYourStream.Read(var Buffer; Count: Integer): Integer;
begin ShowMessage(Buffer); und auch
Delphi-Quellcode:
geht nicht weil Buffer auch kein Integer ist. Buffer ist undefiniert und wird deshalb einfach als Pointer behandelt.
function TYourStream.Read(var Buffer; Count: Integer): Integer;
begin ShowMessage(inttostr(Buffer)); Folgendes geht jedoch:
Delphi-Quellcode:
damit würde man durch den Cast dem Compiler mitteilen das buffer als Integer zu behandeln ist. Da es aber nich in jedem fall ein Integer ist kann man sowas nicht schreiben und daher wird das ganze einfach als pointer behandelt. Obiges ist also nix anderes als
function TYourStream.Read(var Buffer; Count: Integer): Integer;
begin Integer(Buffer) := 5;
Delphi-Quellcode:
Da innerhalb der Funktion ja nicht bekannt ist welcher Typ "Buffer" ist kann somit auch nicht festgestellt werden wie groß der Eventuelle String ist (weil ja nichtmal bekannt ist das es ein String ist) und deshalb musst du vorher den Speicher für den String besorgen (mit SetLength) und dann bei Stream.Read angeben wie groß der verfügbate Speicher ist (der zweite Parameter).
function TYourStream.Read(var Buffer; Count: Integer): Integer;
begin Pinteger(@Buffer)^:= 5; Wenn du in deinem Quelltext an irgend einer Stelle folgendes hast:
Delphi-Quellcode:
so weiß der compiler das '123456' 6 Zeischen lang ist und reserviert automatisch den Speicher was im in dem fall mit dem Stream aber nicht möglich ist da ja nicht bekannt ist wieviel zeischen wirklich zugewiesen werden.
function TYourStream.Read(var Buffer; Count: Integer): Integer;
var LString: String; begin LString := '123456'; |
Alle Zeitangaben in WEZ +1. Es ist jetzt 12:02 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz