Delphi-PRAXiS
Seite 1 von 2  1 2   

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi TFileStream speichert nur Unsinn (https://www.delphipraxis.net/189771-tfilestream-speichert-nur-unsinn.html)

dGeek 19. Jul 2016 17:29

Delphi-Version: XE2

TFileStream speichert nur Unsinn
 
Ich habe folgende Funktion, welche eigentlich einen simplen String mit einer Uhrzeit an eine Textdatei anhängen soll.

Delphi-Quellcode:
var
 aFileStream: TFileStream;
 aLogStr: String;
 aFileName: String;
begin
 aLogStr := DateTimeToStr(Now) + aSystemLogStr + sLineBreak;
 aFileName := vLogFile;

 if FileExists(aFileName) then
  aFileStream := TFileStream.Create(aFileName, fmOpenReadWrite)
 else
  aFileStream := TFileStream.Create(aFileName, fmCreate);

 try
  aFileStream.Seek(0, soEnd);
  aFileStream.WriteBuffer(Pointer(aLogStr)^, Length(aLogStr));
 finally
  aFileStream.Free;
 end;
end;
Das problem ist nun, dass der übergebene String erstens nicht komplett abgespeichert wird ud zweitens in der Datei überall NUL steht.

Bei folgender Variante verschwinden die NUL's, aber der übergebene String wird gar nicht gespeichert:
Delphi-Quellcode:
var
 aFileStream: TFileStream;
 aLogStr: String;
 aFileName: String;
begin
 // aStr z.B. == 'Programm gestartet".

 aLogStr := DateTimeToStr(Now) + '  |   ' + aStr + sLineBreak;
 aFileName := vLogFile;

 if FileExists(aFileName) then
  aFileStream := TFileStream.Create(aFileName, fmOpenReadWrite)
 else
  aFileStream := TFileStream.Create(aFileName, fmCreate);

 try
  aFileStream.Seek(0, soEnd);
  aFileStream.WriteBuffer(Pointer(aLogStr)^, Length(aLogStr));
 finally
  aFileStream.Free;
 end;
end;
Was stimmt da nicht?

Benedikt Magnus 19. Jul 2016 17:37

AW: TFileStream speichert nur Unsinn
 
Warum nimmst du nicht einfach eine Stringlist? Die scheint mir dafür geeigneter bzw. einfacher.

Delphi-Quellcode:
var
  aStringList: TStringList;
  aLogStr: String;
  aFileName: String;
begin
  aLogStr := DateTimeToStr(Now) + aSystemLogStr;
  aFileName := vLogFile;

  aStringList := TStringList.Create;
  try
    if FileExists(aFileName) then aStringList.LoadFromFile(aFileName);
    aStringList.Add(aLogStr);
    aStringList.SaveToFile(aFileName);
  finally
    aStringList.Free;
  end;
end;

dGeek 19. Jul 2016 17:38

AW: TFileStream speichert nur Unsinn
 
Daran hatte ich auch schon gedacht. Nur ist die nicht viel langsamer, oder ist das mittlerweile in Zeiten von SSDs usw ein Irrglaube?

Der schöne Günther 19. Jul 2016 17:40

AW: TFileStream speichert nur Unsinn
 
Dieses komische Pointer/Buffer-Gedöns ist mir unheimlich. Was gewinnt man damit?

Was spricht gegen
Delphi-Quellcode:
TFile.AppendAllText(..)
?

Delphi-Quellcode:
uses System.IoUtils, System.Classes, System.SysUtils;
const
   fileName = 'x:\myFile.abc';
var
   aLogStr: String;
begin
   aLogStr := DateTimeToStr(Now) + 'derp' + sLineBreak;
   TFile.AppendAllText(fileName, aLogStr);
end.
Wenn man es unbedingt mit einem TStream machen möchte: Dann nimm doch einfach WriteData und wandel deinen Text in ein Byte-Array (TBytes) um:

Delphi-Quellcode:
   asBytes := TEncoding.ASCII.GetBytes(aLogStr);
   aFileStream.WriteData(asBytes, Length(asBytes));

Uwe Raabe 19. Jul 2016 17:43

AW: TFileStream speichert nur Unsinn
 
Dir ist aber schon bewusst, daß string ein Unicode-String ist, in dem jedes Zeichen zwei Byte groß ist?

Im Gegensatz dazu erwartet WriteBuffer die tatsächliche Byte-Größe des zu schreibenden Buffers.

Benedikt Magnus 19. Jul 2016 18:21

AW: TFileStream speichert nur Unsinn
 
Zitat:

Zitat von dGeek (Beitrag 1342995)
Daran hatte ich auch schon gedacht. Nur ist die nicht viel langsamer, oder ist das mittlerweile in Zeiten von SSDs usw ein Irrglaube?

Selbst wenn (müsste ich jetzt auch testen), ist dein Log so zeitkritisch?

dGeek 19. Jul 2016 18:23

AW: TFileStream speichert nur Unsinn
 
Nein natürlich nicht ;)

p80286 19. Jul 2016 20:23

AW: TFileStream speichert nur Unsinn
 
Siehe Uwe sowie
Delphi-Quellcode:
mystring[1],length(mystring)*charsize
Je nachdem wie groß die bestehende Datei ist, könnte die Stringlist etwas langsam sein.

Gruß
K-H

dGeek 19. Jul 2016 20:55

AW: TFileStream speichert nur Unsinn
 
Ja das stimmt. Hätte ich mal die Lönge der String nachgezählt, welche abgespeichert wurden, wäre mir das bestimmt aufgefallen. Aber in dem Moment kommt man nicht drauf :P

Sherlock 20. Jul 2016 08:11

AW: TFileStream speichert nur Unsinn
 
Persönliche Meinung (verursacht durch Softwarefehler in allen Betriebssystemen und mit allen Programmiersprachen):
Pointer sind immer der letzte Ausweg. :warn:
Wenn man mit Pointern hantiert, sollte man vorher bereits mindestens einen halben Tag andere Lösungen versucht haben.

Es gibt nur noch ganz seltene Anwendungsfälle, die die Verwendung von Pointern notwendig machen. Dazu gehören WinAPI calls und Assembler. Wenn man also in einer VCL-Anwendung plötzlich Pointer verwenden möchte, sollte man kurz innehalten und nochmal darüber nachdenken. Pointer sind schlicht nicht zeitgemäß und zu fehleranfällig.

Sherlock


Alle Zeitangaben in WEZ +1. Es ist jetzt 06:50 Uhr.
Seite 1 von 2  1 2   

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz