![]() |
TStrings.SaveToFileSafety
Wenn man über SaveToFile z.B. etwas speichert und beim Speichern etwas passiert (z.B. irgendeine Exception), dann sind alle Daten futsch.
Sowohl die Originaldatei, wenn vorher noch eine alte gleichnamige Datei existierte, sowohl eventuell auch die aktuellen Daten. Diese Funktion legt daher eine temporäre Datei an, speichert darin die Stringliste und tauscht im Nachhinein, wenn alles Erfolgreich war, die Dateien erst aus. Als Bonus bleibt die Originaldatei sogar noch erhalten. Ein "normales" SaveToFile überschreibt ja die alten Daten unwiederruflich. Dabei bleibt das alte Original entweder im Papierkorb erhalten oder es ließe sich eine Weile lang über entsprechende Datenrettungstools aus dem Dateisystem wiederherstellen. (gelöschte Dateien werden ja nicht sofort im Dateisystem entfernt/überschrieben)
Delphi-Quellcode:
So wie die Funktion ist, läßt sie sich nur ab Delphi 2009 nutzen,
Uses RTLConsts, ShellAPI;
Type TStringsSafetyHelper = Class Helper for TStrings Procedure SaveToFileSafety(Const FileName: String; BackupToRecycler: Boolean = False); Overload; Procedure SaveToFileSafety(Const FileName: String; Encoding: TEncoding = nil; BackupToRecycler: Boolean = False); Overload; End; Procedure TStringsSafetyHelper.SaveToFileSafety(Const FileName: String; BackupToRecycler: Boolean = False); Begin SaveToFileSafety(FileName, nil, BackupToRecycler); End; Procedure TStringsSafetyHelper.SaveToFileSafety(Const FileName: String; Encoding: TEncoding = nil; BackupToRecycler: Boolean = False); Var H, Hs: THandle; i: Integer; Stream: TStream; SHFile: TSHFileOpStruct; Begin Hs := CreateFile(PChar(FileName), GENERIC_READ, FILE_SHARE_READ, nil, OPEN_EXISTING, 0, 0); If Hs <> INVALID_HANDLE_VALUE Then Begin H := INVALID_HANDLE_VALUE; Try i := -1; Try Repeat Inc(i); H := CreateFile(PChar(Format('%s.%d', [FileName, i])), GENERIC_READ or GENERIC_WRITE, 0, nil, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, Hs); Until (H <> INVALID_HANDLE_VALUE) or (i >= $FFFF); If H = INVALID_HANDLE_VALUE Then Raise EFCreateError.CreateResFmt(@SFCreateErrorEx, [ExpandFileName(FileName), SysErrorMessage(GetLastError)]); Stream := THandleStream.Create(H); Try SaveToStream(Stream, Encoding); Finally Stream.Free; End; FlushFileBuffers(H); If BackupToRecycler Then Begin SHFile.Wnd := 0; SHFile.wFunc := FO_DELETE; SHFile.pFrom := PChar(FileName + #0); SHFile.pTo := nil; SHFile.fFlags := FOF_ALLOWUNDO or FOF_NOCONFIRMATION or FOF_NOERRORUI or FOF_NO_UI or FOF_SILENT; If not SHFileOperation(SHFile) Then Raise EFCreateError.CreateResFmt(@SFCreateErrorEx, [ExpandFileName(FileName), SysErrorMessage(GetLastError)]); End Else If not Windows.DeleteFile(PChar(FileName)) Then Raise EFCreateError.CreateResFmt(@SFCreateErrorEx, [ExpandFileName(FileName), SysErrorMessage(GetLastError)]); If not MoveFile(PChar(Format('%s.%d', [FileName, i])), PChar(FileName)) Then Begin i := -1; Raise EFCreateError.CreateResFmt(@SFCreateErrorEx, [ExpandFileName(FileName), SysErrorMessage(GetLastError)]); End; Except If i <> -1 Then Windows.DeleteFile(PChar(Format('%s.%d', [FileName, i]))); Raise; End; Finally CloseHandle(H); End; End Else SaveToFile(FileName, Encoding); End; aber indem man einfach nur den Encoding-Parameter entfernt, würde es bis runter zu Delphi 2006 / Turbo Delphi funktionieren. Und für noch ältere Delphi-Versionen muß man sich "nur" eine eigene Klasse/Funktion aus diesem Class-Helper basteln. :angel: Die ganze Speicherroutine liese sich auch auf andere Dateispeicherungen anwenden, nicht nur für Stringlisten. Dafür müßte man dann halt nur die Speicherroutinen des Objektes anpassen/austauschen und z.B. einen passenden Class-Helper erstellen. |
AW: TStrings.SaveToFileSecure
Wobei die Bezeichnung ...Secure etwas ungünstig ist, da man eher erwartet, das verschlüsselt o.ä. wird
|
AW: TStrings.SaveToFileSecure
Bin für Vorschläge offen ... mir war einfach nix besseres eingefallen. :stupid:
|
AW: TStrings.SaveToFileSecure
Mhm...vielleicht mit einem Wortspiel? :)
TStrings.SafeToFile() :D oder...WriteSafeToFile() ; |
AW: TStrings.SaveToFileSecure
Vielleicht .SaveToFileBackuped() oder noch besser wäre eine überladenen Variante mit ensprechenden Parameter
|
AW: TStrings.SaveToFileSecure
Wie wärs mit SafeSaveToFile()? ;-)
Im Englischen gibt es ja den Unterschied zwischen Safety und Security... |
AW: TStrings.SaveToFileSecure
Und noch ein paar Vorschläge:
SaveToFileProved() SaveToFileReliable() ; SaveCertainlyToFile() |
AW: TStrings.SaveToFileSafety
Besser so?
Die Wortspiele, wie SafeToFile, würde ich nicht gern nutzen. - Erstmal sieht es so zu ähnlich aus (Verwechslungsgefahr) - und dann macht es sich mit einem Suffix besser, bezüglich der Autovervollständigung. |
AW: TStrings.SaveToFileSafety
Fast. Klingt nun etwas komisch (also der Englische Ausdruck). "SaveToFileSafely" (oder auch "SaveToFileSafe") wäre da korrekter.
|
AW: TStrings.SaveToFileSafety
SaveToFileWithHaarSpaltereiWort()
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 22:48 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