Delphi-PRAXiS
Seite 1 von 3  1 23      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Delphi beliebige Datei in Stream speichern (https://www.delphipraxis.net/2515-beliebige-datei-stream-speichern.html)

Evilboyz 27. Jan 2003 14:42


beliebige Datei in Stream speichern
 
Hallo Forum!

Wie schreibe ich eine beliebige Datei in einen Stream und wie bekomme ich die Datei dort wieder heraus?
Soweit ich das bisher herausgefunden habe, muss ich auf alle Fälle SaveToStream verwenden. Ich habe jetzt versucht, mit AssignFile eine Dateivariable zu initialisieren um diese dann per SaveToStream in einen Stream zu packen, bin ich da völlig auf dem Holzweg? :freak:

Evilboyz 27. Jan 2003 15:12

So, also im Moment sieht mein Code wie folgt aus:

Code:
procedure TForm1.ServerSocketClientRead(Sender: TObject;
  Socket: TCustomWinSocket);
  var DataEnvelope : TStream;
      data :        file;
begin
     AssignFile(data, 'datei\test.exe');
     data.SaveToStream(DataEnvelope, dfBinary);
     closefile(data);
     Socket.SendStream(DataEnvelope);
     DataEnvelope.Free;
end;
Als Fehlermeldung bekomme ich in der Zeite, in der SaveToStream steht: "Record, Objekt oder Klassentyp erforderlich"

Christian Seehase 27. Jan 2003 15:46

Moin Evilboyz,

Du vermischt da verschiedene Methoden auf Dateien zuzugreifen.
Schau Dir am Besten mal TFileStream an.

Beispiel:

Delphi-Quellcode:
var
  fsWork : TFileStream;
  sBuffer : string;

begin
  fsWork := TFileStream.Create(DateiPfad,Modus);
  sBuffer := StringOfChar(#00,fsWork.Size);
  try
    // Komplett in Buffer einlesen
    fsWork.Read(sBuffer[1],fsWork.Size);
  finally
    FreeAndNil(fsWork);
  end;
  // Mit dem Buffer arbeiten
end;

Evilboyz 28. Jan 2003 08:12

Ahja, jetzt scheint es zu funktionieren ... Danke Dir!!!

:coder:

Evilboyz 28. Jan 2003 09:26

Doch noch nicht ganz ....
Also die Sache mit
Zitat:

Zitat von Christian Seehase
fsWork := TFileStream.Create(DateiPfad,Modus);

ist mir jetzt klar, was passiert aber in dieser Zeile?
Zitat:

Zitat von Christian Seehase
sBuffer := StringOfChar(#00,fsWork.Size);

StringOfChar gibt jetzt also (lt. Hilfe), fsWork.size mal #00 zurück, aber was hat es mitdem #00 auf sich? :freak:

Was ich außerdem noch nicht hinbekommen habe, ist den Stream auf der anderen Seite wieder in eine Datei zu schreiben, ich hab den jetzt über SendStream abgeschickt und auf Clientseite per receiveBuf empfangen (irgendwas kommt da immerhin schonmal an). SaveToFile meckert mir der Compiler dann allerdings an und sagt: "Undefinierter Bezeichner: SaveToFile"
Irgendwie habe ich den Eindruck, dass ich immernoch verschiedene Möglichkeiten der Übertragung vermische!

Evilboyz 28. Jan 2003 11:41

Tja, da ich natürlich nicht aufgebe und beim Nachlesen (Entwicklerhandbuch - Borland D5) immer wieder neue Erkenntnisse erlange (so sollte es ja auch sein), schreibe ich eben mal wieder selber eine Antwort.
Ich sende also, wie schon gesagt, per SendStream meinen Stream. lt. Seite 30-12 (ist ja auch egal) scheint es aber keine ReceiveStream Methode auf der anderen Seite zu geben. Wenn ich die Daten per ReceiveBuf empfange, dann scheint die Übertragung Byteweise statt zu finden und ich muss irgendwie darauf warten, bis die Übertragung fertig ist. Wie also mache ich das?
Ja und die Sache mit #00 ist mir nach wie vor unklar!

Christian Seehase 28. Jan 2003 12:05

Moin Evilboyz,

statt Byteweise zu lesen, könntest Du ja auch immer Blockweise lesen, bis nichts mehr zu lesen ist (Rückgabewert -1).

Mit dem StringOfChar wird die Buffergrösse auf den zumindest erforderlichen Platz gesetzt, und gleichzeitig auf #00 initialisiert, damit der Buffer einen definierten Inhalt hat.
Wenn es sich um grössere Dateien handelt, könnte man natürlich auch (wie bei ReceiveBuf ;-) ) Blockweise lesen, und dann je Lesevorgang die Initialisierung wiederholen, damit zumindest der Rest des Buffers (falls die Buffergrösse kein Vielfaches der zu lesenden Anzahl Byte ist) mit einem definierten Wert belegt ist.

Die #00 nehme ich, da dies ein Wert ist, der zumindest in Texten eigentlich nicht auftauchen kann (Unicode mal ausgenommen), und somit das erste auftreten einer #00 sich oft als Ende der Daten ansehen lässt (wie bei nullterminierten Strings, wie sie bei den Windows API Funktionen üblich sind).

Beim Einlesen (ob nun über TFileStream.Read, oder über ReceiveBuf) könnte das dann so aussehen:
  1. Buffer initialisieren
  2. Daten lesen (Länge = Bufferlänge)
  3. Keine Daten gelesen dann fertig
  4. Daten in gelesener Länge verarbeiten
  5. Weiter mit 1

Evilboyz 28. Jan 2003 15:47

Hi,

ich bekomme es immer noch nicht hin! :cry: Folgenden Code habe ich jetzt also auf Serverseite. Wie finde ich bei SendBuf nun aber die den Int - Wert, den ich übergeben muss? Wenn ich testhalber 1000 eintrage wird etwas gesendet, wenn ich die Länge von SBuffer ermitteln und diese übergeben will, bekomme ich einen Fehler beim Compilieren.
Code:
procedure TForm1.ServerSocketClientRead(Sender: TObject;
  Socket: TCustomWinSocket);
  var fsWork : TFileStream;
      sBuffer : String;
begin
     Events.Lines.Add(Socket.ReceiveText);

     fsWork := TFileStream.Create('datei\test.exe', fmOpenRead);
     sBuffer := StringOfChar(#00,fsWork.Size);
     try
         Komplett in Buffer einlesen
        fsWork.Read(sBuffer[1],fsWork.Size);
     finally
        FreeAndNil(fsWork);
     end;
         Socket.SendBuf(sBuffer,1000);
end;
Auf Clientseite kann ich doch nun mit
Code:
Socket.ReceiveBuf(Data, Socket.ReceiveLength);
die empfangenen Daten in "Data" (Data : TStream) schreiben, oder?
Langsam komme ich mir echt schon blöd vor, aber ich stehe voll auf dem Schlauch!

Evilboyz 28. Jan 2003 15:50

Zitat:

Zitat von Christian Seehase
  1. Buffer initialisieren
  2. Daten lesen (Länge = Bufferlänge)
  3. Keine Daten gelesen dann fertig
  4. Daten in gelesener Länge verarbeiten
  5. Weiter mit 1

Das bedeutet also, ich lese die Daten in meine Buffervariable (String) und fülle eine Datei nach und nach mit diesen empfangenen Teilstrings. Das wiederhole ich solange, bis keine Daten mehr gelesen werden. :pale:

Evilboyz 28. Jan 2003 15:56

ist dieser Code richtig???
Code:
procedure TForm1.ClientSocket1Read(Sender: TObject;
  Socket: TCustomWinSocket);
  var Data : TStream;
      sBuffer : String;
begin
     while Socket.ReceiveBuf(sBuffer, Socket.ReceiveLength)<>-1 do begin
           Data.Write(sBuffer, length(sBuffer));
     end;
     Data.Free;
end;
:coder: ... *nichtaufgibt*


Alle Zeitangaben in WEZ +1. Es ist jetzt 09:59 Uhr.
Seite 1 von 3  1 23      

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