![]() |
StreamWrite erzeugt nur 0 Byte-File
Hallo,
ich nutze folgende Code um eine binäre Datei zu erzeugen.
Delphi-Quellcode:
Leider wird die Datei aber immer nur nit einer Länge von 0 Byte angelegt.
procedure Tfrm_main.Button1Click(Sender: TObject);
var aFileBuffer : array of byte; iFileLength, ix, iByteCounter : integer; datei : tfilestream; bStreamOk : boolean; s_filename, startpfad : string; begin iFileLength := strtoint(edit1.text); // Aktueller Wert: '20980826' // Array erzeugen setLength(aFileBuffer, iFileLength); for ix := 0 to (iFileLength - 1) do aFileBuffer[ix] := 55; // Startpfad ermitteln getdir(0, startpfad); // Startpfad einlesen if (startpfad[length(startpfad)] <> '\') then startpfad := startpfad + '\'; // Pfad ggf. korrigieren // Dateiname zuweisen s_filename := startpfad + edit2.Text; // Aktueller Wert: 'data.bin' bStreamOk := true; try datei := Tfilestream.create(s_filename, fmcreate or fmShareExclusive); except bStreamOk := false; end; if (bStreamOk = true) then begin // Schreiben der DateiInhalte in den Stream try iByteCounter := datei.Write(aFileBuffer, iFileLength); finally datei.free; end; // Prüfen ob die korrekte Anzahl Bytes geschrieben wurde if (iByteCounter <> iFileLength) then showmessage('Stream wurde erzeugt, hat aber die falsche Größe.') else showmessage('Stream wurde erzeugt.'); end else begin showmessage('Stream konnte nicht erzeugt werden.'); end; end; Was bitte mache ich denn falsch? Gruß Holger. :gruebel: |
Re: StreamWrite erzeugt nur 0 Byte-File
Delphi-Quellcode:
Statt
iByteCounter := datei.WriteBuffer(aFileBuffer, iFileLength);
Delphi-Quellcode:
besser
if (bStreamOk = true) then
Delphi-Quellcode:
if bStreamOk then
|
Re: StreamWrite erzeugt nur 0 Byte-File
Danke
|
Re: StreamWrite erzeugt nur 0 Byte-File
Hallo little Budda,
Ich habe Deinen Code einmal ausprobiert und leicht geändert:
Delphi-Quellcode:
und siehe da es wird eine 123Byte große Datei erzeugt.
procedure TForm1.Button1Click(Sender: TObject);
var aFileBuffer : array of byte; iFileLength, ix, iByteCounter : integer; datei : tfilestream; bStreamOk : boolean; s_filename, startpfad : string; begin [b]iFileLength := 123; // Aktueller Wert: '20980826'[/b] // Array erzeugen setLength(aFileBuffer, iFileLength); for ix := 0 to (iFileLength - 1) do aFileBuffer[ix] := 55; // Startpfad ermitteln getdir(0, startpfad); // Startpfad einlesen if (startpfad[length(startpfad)] <> '\') then startpfad := startpfad + '\'; // Pfad ggf. korrigieren // Dateiname zuweisen [b] s_filename := 'c:\temp\test.bin'; // Aktueller Wert: 'data.bin'[/b] bStreamOk := true; try datei := Tfilestream.create(s_filename, fmcreate or fmShareExclusive); except bStreamOk := false; end; if (bStreamOk = true) then begin // Schreiben der DateiInhalte in den Stream try iByteCounter := datei.Write(aFileBuffer, iFileLength); finally datei.free; end; // Prüfen ob die korrekte Anzahl Bytes geschrieben wurde if (iByteCounter <> iFileLength) then showmessage('Stream wurde erzeugt, hat aber die falsche Größe.') else showmessage('Stream wurde erzeugt.'); end else begin showmessage('Stream konnte nicht erzeugt werden.'); end; end; Schau Dir im Debugger die Übergabe der Dateigröße einmal an. Gruß K-H |
Re: StreamWrite erzeugt nur 0 Byte-File
Also irgendwie sieht euer Code komisch aus.
Dieses bStreamOK stört mich zum Beispiel. Das kann man doch so lösen:;
Delphi-Quellcode:
Desweiteren würde ich die Daten/Code von der Oberfläche trennen, also den Code in eine separate Methode auslagern, die von der Schaltfläche aufgerufen wird:
datei := TFileStream.Create(...);
if Assigned(datei) then begin try try BytesWritten := datei.Write(...); except raise Exception.... finally datei.Free; end; end;
Delphi-Quellcode:
procedure Tfrm_main.Button1Click(Sender: TObject);
begin try SchreibeDatei(...); except on E: Exception do ShowMessage(E.Message); end; |
Re: StreamWrite erzeugt nur 0 Byte-File
GetDir(0, x); ist eine schlechte Wahl, da es der aktuelle Pfad ist und dieser somit nicht zwingend der "Startpfad" ist. Ein Open/SaveDialog z.B. ändern diesen Standardpfad standardmässig mit den Nutzeraktionen. Hier solltest du lieber auf ParamStr(0) zurück greifen.
Auch ist dein Test auf ein abschließenden Backslash eine Fehlerquelle, wenn der string mal leer ist. Dann würde es zu einer Zugriffsverletzung bzw. einem Range Check Error kommen. Nutze lieber dazu die von der VCL definierten Funktion IncludeTrailingPathDelimiter(). Deine Prüfung ob die Erstellung der TFileStream Instanz erfolgreich war, könnte man noch in zwei Dingen ändern/verbessern: Zum einen würde eine Exception aus dem Constructor die Instanzenvariable niemals zuweisen, da er durch die Exception diesen Coder erst gar nicht mehr ausführt. Von daher kannst du auch einfach die Instanzenvariable auf NIL setzen vor dem try und dann danach abprüfen, ob diese ungleich nil ist. Und zum anderen kann der Constructor nur durch eine Exception abgebrochen werden und somit kannst du auch einfach den Except Block hinter deine Dateiroutinen verschieben, weil durch die Exception würde er diese nicht mehr ausführen und am Ende gefangen werden. /EDIT: Toll, alle schreiben während ich hier tippe. @Luckie: Du musst explizit datei auf nil setzen, weil es eine (nicht initialisierte) lokale Variable ist. Und wenn, ein Constructor gibt niemals nil zurück, sondern wird höchstens mit einer Exception abgebrochen und damit würde deine Abfrage erst gar nicht mehr zum Zuge kommen. Und warum mit Except eine Exception fangen um dann eine eigene zu werfen? Warum willst du die zusätzlichen Informationen der originalen Exception wegwerfen? Warum eine unspezifizierte eigene Exception? Wenn, dann wieder re-raisen mit raise, aber dann brauchste auch kein Except Block, den kannst du dir dann auch gleich sparen. Und es fehlt ein end; bei deinem Code... @p80286: Wie schon erwähnt, würde ich den Vergleich auf true unbedingt abändern! |
Re: StreamWrite erzeugt nur 0 Byte-File
Zitat:
|
Re: StreamWrite erzeugt nur 0 Byte-File
Hallo Little Budda,
sorry ich hab mich etwas vergallopiert, Aus mir unerfindlichen Gründen ist bei der Dateigröße von $3AEC (ca 15 000) Schluß mit lustig. Da liegt das Problem weniger in Deinem Code als irgendwo anders. Gruß K-H |
Re: StreamWrite erzeugt nur 0 Byte-File
@Muetze
Naja halte ich für Geschmackssache. Deine Version gefällt mir besser aber ist sie darum richtiger. Ist schließlich little Buddas Code und er muß sich darin zurechtfinden. Gruß K-H |
Re: StreamWrite erzeugt nur 0 Byte-File
Zitat:
Im gesamten dann:
Delphi-Quellcode:
Warum so?
procedure Tfrm_main.Button1Click(Sender: TObject);
begin try if DateiSchreiben(ExtractFilePath(ParamStr(0)) + Edit2.Text, StrToIntDef(Edit1.Text, 0)) then MessageDlg('Datei wurde erfolgreich gespeichert.', mtInformation, [mbOk], 0); except on e:exception do MessageDlg(format('Es ist beim Schreiben der Datei ein Fehler aufgetreten.'#10#13#10#13'(%s) %s', [E.Classname, E.Message]), mtError, [mbOk], 0); end; end; function DateiSchreiben(const AFilename: string; const AFileSize: Int64); const coBlockSize = 16384; var lStream: TStream; lFileData: string; lBytesToWrite: Int64; lWritten: Integer; begin result := false; // Erstmal den Stream öffnen. Wenn das nicht klappt, brauch ich kein Array... lStream := TFileStream.Create(AFilename, fmCreate or fmShareDenyWrite); try lFileData := StringOfChar(coBlockSize, #55); lBytesToWrite := AFileSize; while ( lBytesToWrite > 0 ) do begin lWritten := lStream.WriteBuffer(lFileData[1], Min(lBytesToWrite, coBlockSize)); if lWritten <> Min(lBytesToWrite, coBlockSize) then exit; Dec(lBytesToWrite, lWritten); end; result := true; finally lStream.free; end; end; 1. Ein dynamisches Array ohne Begrenzung ist schlecht, weil bei einer 2 GB Datei möchte ich mal sehen, was zu der Speichermanager zu der Alloziierung sagt. 2. Da die Daten immer gleich waren, hat es sich hier angeboten StringOfChar() zu nutzen. 3. Exceptions, egal wo, werden geworfen und kommen so richtig beim Aufrufer an. 4. Der Rückgabewert gibt den eigentlichen Erfolg zurück. Man kann alternativ mit der Verlagerung des Exception Handlers in die Funktion diese zu einer reinen Funktion machen, die alles über das result regelt. 5. Oberfläche und Implementation sind getrennt. Alles wichtige was die Funktion braucht, wird ihr übergeben und ausserhalb entsprechend aufbereitet. Und allgemeiner Hinweis: Wenn es nur darum geht eine Platzverschwendung mit bestimmter Größe zu erzeugen, dann einfach TFileStream anlegen und die Size Property setzen. Der Inhalt der Datei ist dann aber Zufall. Zitat:
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 13:59 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 by Thomas Breitkreuz