![]() |
Mit BlockRead() Datei kopieren
Hi,
ich möchte eine Datei einlesen und Stück für Stück wieder, als eine Kopie, zusammensetzen. Dies habe ich auch schon geschafft, indem ich immer ein Byte kopiert habe. Das dauert aber viel zu lange. Desshalb möchte ich gerne 1024 Bytes kopieren. Am Ende möchte ich nämlich die Bytes von einem Server zu einem Klienten senden, quasi als Download-Feature, dass der Client Dateien vom Server herunterladen kann. Leider schaffe ich nicht mal das bloße, stückweise Kopieren. -.- Ich bekomme immer einen E/A - Fehler 1784. Mein Code:
Delphi-Quellcode:
Ich weiß nicht mehr weiter. :(
unit Unit1;
interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm1 = class(TForm) Memo1: TMemo; procedure FormCreate(Sender: TObject); private { Private-Deklarationen } public { Public-Deklarationen } end; type TDLFile = array[0..1024-1] of Byte; var Form1: TForm1; tmpReplace: String = 'C:\test.exe'; tmpKopie: String = 'C:\test_copy.exe'; sizeDlDat: Cardinal = 0; dlCounter: LongInt = 0; implementation {$R *.dfm} function SizeOfFile(lpFileStr: String):Cardinal; var hDat: File of Byte; begin result := 0; if FileExists(lpFileStr) then begin AssignFile(hDat, lpFileStr); ReSet(hDat); result := FileSize(hDat); CloseFile(hDat); end; end; procedure WriteIntoDownloadedDat(bByteDat: TDLFile); var hDat: File; g: LongInt; begin if FileExists(tmpKopie) then begin AssignFile(hDat, tmpKopie); ReSet(hDat, 1024); //Öffnen, falls sie existiert. Seek(hDat, soFromEnd); //An das Ende der Datei springen BlockWrite(hDat, bByteDat, sizeof(bByteDat)); //Die neuen 1024 Bytes schreiben. Hier E/A - Fehler 1784. CloseFile(hDat); //Schliessen end else begin AssignFile(hDat, tmpKopie); ReWrite(hDat, 1); //Datei neu erstellen, falls sie nicht existiert. BlockWrite(hDat, bByteDat, sizeof(bByteDat)); //Die ersten 1024 Bytes schreiben CloseFile(hDat); //Schliessen end; end; procedure TForm1.FormCreate(Sender: TObject); var hDlDat: File; bDlDat: TDLFile; g: Integer; begin memo1.Clear; if FileExists(tmpReplace) then begin sizeDlDat := SizeOfFile(tmpReplace)-1; //Dateigröße - 1 memo1.Lines.Add('Full size: ' + inttostr(sizeDlDat) + ' bytes'); AssignFile(hDlDat, tmpReplace); //Dateihandle erstellen ReSet(hDlDat, 1024); //Datei öffnen (1024 bytes) while not eof(hDlDat) do //Solange wir nicht am Ende der Datei sind.. begin BlockRead(hDlDat, bDlDat[0], sizeof(bDlDat[0])); //1024 Bytes einlesen WriteIntoDownloadedDat(bDlDat); //Prozedur aufrufen und die Bytes übergeben. Seek(hDlDat, soFromCurrent); //Die 1024 kopierten Bytes überspringen, um zu den nächsten 1024 Bytes zu kommen Application.ProcessMessages; end; CloseFile(hDlDat); //Datei schliessen. sizeDlDat := 0; tmpReplace := ''; memo1.Lines.Add('FINISHED!'); end; end; end. Hoffe, ihr könnt mir helfen. |
Re: Mit BlockRead() Datei kopieren
Ohne auf deinen Code einzugehen, ich habe da folgende Routine:
Delphi-Quellcode:
Der Procedurkopf sollte eigentlich alles erklären. Die globale Variable FastCopyResult ist global deklariert, das würde ich heute anders machen ...
procedure FastCopy_All(SouName,DesName:String;DelSou:Boolean);
const BufferSize = 32768; var Sou,Des : file; Buffer : Array[1..BufferSize] of Byte; NumRead, NumSave : Integer; begin CopiedBytes:=0; AssignFile(Sou,SouName); {$I-} reset(Sou,1); {$I+} FastCopyResult:=IOresult; if FastCopyResult<>0 then exit; AssignFile(Des,DesName); {$I-} rewrite(Des,1); {$I+} FastCopyResult:=IOresult; if FastCopyResult<>0 then exit; repeat BlockRead (Sou,Buffer,SizeOf(Buffer),NumRead); BlockWrite(Des,Buffer,NumRead, NumSave); inc(CopiedBytes,NumSave); Application.ProcessMessages; until (NumRead=0) or (NumSave<>NumRead); CloseFile(Sou); CloseFile(Des); if DelSou then erase(Sou); end; |
Re: Mit BlockRead() Datei kopieren
Zitat:
Was du brauchst ist eine Blockgröße von 1. Also Reset(hDat, 1); Dann entspricht der dritte Parameter einer Einheit von einem Byte. Aber warum nimmst du nicht gleich einen TFileStream her die die alten TurboPascal Funktionen ersetzen. |
Re: Mit BlockRead() Datei kopieren
Danke, habe es nun hinbekommen, obwohl er ein paar Bytes zuviel schreibt. :p
|
Re: Mit BlockRead() Datei kopieren
Hätte man in die Delphi Hilfe geguckt...
Beispiel aus der Delphi Hilfe
Delphi-Quellcode:
var FromF, ToF: file;
NumRead, NumWritten: Integer; Buf: array[1..2048] of Char; begin if OpenDialog1.Execute then { Dialog zum Dateiöffnen anzeigen } begin AssignFile(FromF, OpenDialog1.FileName); Reset(FromF, 1); { Datensatzgröße = 1 } if SaveDialog1.Execute then { Dialog zum Speichern anzeigen } begin AssignFile(ToF, SaveDialog1.FileName); { Ausgabedatei öffnen } Rewrite(ToF, 1); { Datensatzgröße = 1 } Canvas.TextOut(10, 10, 'Kopieren von ' + IntToStr(FileSize(FromF)) + ' Byte...'); repeat BlockRead(FromF, Buf, SizeOf(Buf), NumRead); BlockWrite(ToF, Buf, NumRead, NumWritten); until (NumRead = 0) or (NumWritten <> NumRead); CloseFile(FromF); CloseFile(ToF); end; end; end; Dann wird nix zuviel kopiert^^ |
Re: Mit BlockRead() Datei kopieren
Hallo,
bei BlockRead muss die Dateigröße immer ein Vielfaches der Blockgröße sein - deshalb ist BlockSize=1 irgendwie optimal. Mit Streams reduziert sich der Code eigentlich auf die Methode CopyFrom():
Delphi-Quellcode:
Getippt und nicht getestet.
procedure FileCopy(fnSource, fnTarget: TFilename);
var fsSource, fsTarget: TStream; begin fsSource := TFileStream.Create(fnSource, fmOpenRead); try fsTarget := TFileStream.Create(fnTarget, fmCreate); try fsTarget.CopyFrom(fsSource, 0); finally fsTarget.Free; end; finally fsSource.Free; end; end; Grüße vom marabu |
Re: Mit BlockRead() Datei kopieren
Ich schaue immer in die Delphi Hilfe, aber diesmal konnte ich nichts finden.
Sonst würde ich ja nicht fragen. Mein Code sieht im Moment so aus:
Delphi-Quellcode:
Wenn ich anstatt das Socket.SendBuf WriteIntoDownloadedDat() benutze, dann klappt es.
if FileExists(tmpReplace) then
begin sizeDlDat := SizeOfFile(tmpReplace)-1; AssignFile(hDlDat, tmpReplace); ReSet(hDlDat, 1); g := 0; repeat BlockRead(hDlDat, bDlDat, 1024); Socket.SendBuf(bDlDat, 1024); inc(g, 1024); Seek(hDlDat, soFromBeginning+g); Sleep(7); Application.ProcessMessages; until g >= (sizeDlDat-1024); CloseFile(hDlDat); sizeDlDat := 0; end; tmpReplace := ''; Nur leider sendet er immer ganz komische Bytes. Da weiß ich leider nicht mehr weiter. |
Re: Mit BlockRead() Datei kopieren
Hallo,
du lässt BlockRead() immer 1024 Byte lesen, aber beim letzten Lesevorgang ist die Chance groß, dass weniger als 1024 Byte gelesen werden können. Du kannst die Zahl der wirklich gelesenen Bytes in einer Variablen erhalten, die du als vierten Parameter von BlockRead() übergibst. Diese Variable kannst du dann zum Steuern von SendBuf() verwenden, damit nicht mehr als die gelesenen Bytes versendet werden.
Delphi-Quellcode:
Wieder getippt und nicht getestet.
// look ma, no hands!
procedure FileSend(const fn: TFilename; socket: TBaseSocket); var s: TStream; begin s := TFileStream.Create(fn, fmOpenRead); try socket.SendStream(s); finally s.Free; end; end; Freundliche Grüße |
Re: Mit BlockRead() Datei kopieren
Naja, das Problem ist im Moment, dass die gedownloadete Datei sich nicht im geringsten
mit der originalen Datei mehr ähnelt, wenn ich sie abgleiche. Die Kopie des Originals hat immer das selbe Muster, also z.B. so: ++++++++++++ ++++ ++++++++++++ ++++ ++++++++++++ ++++ ++++++++++++ ++++ Die originale Datei dagegen hat das richtige Muster. Auch enthält die kopierte Datei nicht mehr die Strings, welche die originale Datei enthält. Das war jetzt bisschen doof zu erklären. :x Ich hoffe ihr versteht, was ich meine. :/ |
Re: Mit BlockRead() Datei kopieren
Zitat:
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 11:55 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