AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

TStrings.SaveToFileSafety

Ein Thema von himitsu · begonnen am 28. Jun 2010 · letzter Beitrag vom 28. Jun 2010
Antwort Antwort
Seite 1 von 2  1 2      
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.184 Beiträge
 
Delphi 12 Athens
 
#1

TStrings.SaveToFileSafety

  Alt 28. Jun 2010, 12:45
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:
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;
So wie die Funktion ist, läßt sie sich nur ab Delphi 2009 nutzen,
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.

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.
$2B or not $2B

Geändert von himitsu (28. Jun 2010 um 13:02 Uhr)
  Mit Zitat antworten Zitat
mkinzler
(Moderator)

Registriert seit: 9. Dez 2005
Ort: Heilbronn
39.861 Beiträge
 
Delphi 11 Alexandria
 
#2

AW: TStrings.SaveToFileSecure

  Alt 28. Jun 2010, 12:47
Wobei die Bezeichnung ...Secure etwas ungünstig ist, da man eher erwartet, das verschlüsselt o.ä. wird
Markus Kinzler
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.184 Beiträge
 
Delphi 12 Athens
 
#3

AW: TStrings.SaveToFileSecure

  Alt 28. Jun 2010, 12:51
Bin für Vorschläge offen ... mir war einfach nix besseres eingefallen.
$2B or not $2B
  Mit Zitat antworten Zitat
blackfin
(Gast)

n/a Beiträge
 
#4

AW: TStrings.SaveToFileSecure

  Alt 28. Jun 2010, 12:53
Mhm...vielleicht mit einem Wortspiel?

TStrings.SafeToFile()

oder...WriteSafeToFile() ;
  Mit Zitat antworten Zitat
mkinzler
(Moderator)

Registriert seit: 9. Dez 2005
Ort: Heilbronn
39.861 Beiträge
 
Delphi 11 Alexandria
 
#5

AW: TStrings.SaveToFileSecure

  Alt 28. Jun 2010, 12:54
Vielleicht .SaveToFileBackuped() oder noch besser wäre eine überladenen Variante mit ensprechenden Parameter
Markus Kinzler
  Mit Zitat antworten Zitat
Benutzerbild von mirage228
mirage228

Registriert seit: 23. Mär 2003
Ort: Münster
3.750 Beiträge
 
Delphi 2010 Professional
 
#6

AW: TStrings.SaveToFileSecure

  Alt 28. Jun 2010, 12:54
Wie wärs mit SafeSaveToFile()?

Im Englischen gibt es ja den Unterschied zwischen Safety und Security...
David F.

May the source be with you, stranger.
PHP Inspection Unit (Delphi-Unit zum Analysieren von PHP Code)
  Mit Zitat antworten Zitat
blackfin
(Gast)

n/a Beiträge
 
#7

AW: TStrings.SaveToFileSecure

  Alt 28. Jun 2010, 12:58
Und noch ein paar Vorschläge:

SaveToFileProved()

SaveToFileReliable() ;

SaveCertainlyToFile()
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.184 Beiträge
 
Delphi 12 Athens
 
#8

AW: TStrings.SaveToFileSafety

  Alt 28. Jun 2010, 13:04
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.
$2B or not $2B

Geändert von himitsu (28. Jun 2010 um 13:06 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von mirage228
mirage228

Registriert seit: 23. Mär 2003
Ort: Münster
3.750 Beiträge
 
Delphi 2010 Professional
 
#9

AW: TStrings.SaveToFileSafety

  Alt 28. Jun 2010, 13:07
Fast. Klingt nun etwas komisch (also der Englische Ausdruck). "SaveToFileSafely" (oder auch "SaveToFileSafe") wäre da korrekter.
David F.

May the source be with you, stranger.
PHP Inspection Unit (Delphi-Unit zum Analysieren von PHP Code)
  Mit Zitat antworten Zitat
blackfin
(Gast)

n/a Beiträge
 
#10

AW: TStrings.SaveToFileSafety

  Alt 28. Jun 2010, 13:08
SaveToFileWithHaarSpaltereiWort()
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 23:12 Uhr.
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