| Autor |
Beitrag |
D. Annies
      
Beiträge: 1843
windows 7
D6 Enterprise, D7 Pers und TD 2006
|
Verfasst: Sa 20.11.10 10:21
Hi, Delpher,
jedesmal, wenn auf Sommer- Winterzeit umgestellt wird, werden (bisher) viele Dateien, deren Zeit sich genau um diese eine Stunde unterscheidet, mitkopiert, obwohl das ja unnötig ist.
Ich vermute, dass ich eine AND-Bedingung an der markierten Stelle ergänzen muss, aber welche und wie?
Der bisherige, funktionierende Code ist:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15:
| if FileDateToDateTime(FileAge(work_filename)) <> FileDateToDateTime(FileAge(home_filename))
then begin erg := xmessagedlg('ArchivBit wurde gesetzt' +#13 + 'Soll ' + work_filename + ' '+#13+ datetimetostr(filedatetodatetime(FileAge(work_filename))) +#13+ 'durch ' + home_filename + ' '+#13+ datetimetostr(filedatetodatetime(FileAge(home_filename))) +#13+ ' ersetzt werden?', mtConfirmation, [mbYes, mbno, mbcancel], ['ja', 'nein', 'Abbrechen'], self.font); case erg of mryes : CopyFile(PChar(home_filename), PChar(work_filename), FALSE); mrcancel : raus := true; end; end; |
Danke, Detlef
_________________ ut vires desint, tamen est laudanda voluntas
|
|
F34r0fTh3D4rk
      
Beiträge: 5284
Erhaltene Danke: 27
Win Vista (32), Win 7 (64)
Eclipse, SciTE, Lazarus
|
Verfasst: Sa 20.11.10 12:53
Ich weiß zwar nicht, was der Code tut (bzw. in welchen Intervallen er ausgeführt wird), aber würde es nicht reichen, zu prüfen, ob die Differenz größer als eine Stunde ist? Oder würde das den allgemeinen Fall beeinflussen?
|
|
D. Annies 
      
Beiträge: 1843
windows 7
D6 Enterprise, D7 Pers und TD 2006
|
Verfasst: Sa 20.11.10 14:12
Ja, das wäre genau richtig und ok, wenn ich sagen könnte: Wenn die Differenz (genau) eine Stunde beträgt, dann
nicht speichern [weil ja nichts verändert ist], nur neuer Zeitstempel gesetzt]
Gruß, Detlef
_________________ ut vires desint, tamen est laudanda voluntas
|
|
F34r0fTh3D4rk
      
Beiträge: 5284
Erhaltene Danke: 27
Win Vista (32), Win 7 (64)
Eclipse, SciTE, Lazarus
|
Verfasst: Sa 20.11.10 14:32
Das gilt ja aber nur bei der Umstellung auf die Sommerzeit, bei der Winterzeit ist ja eine Stunde doppelt vorhanden.
Du könntest prüfen, um welches Datum es sich handelt. Wikipedia sagt:
| Zitat: | Die Umstellung von der Normal- auf die Sommerzeit findet am letzten Sonntag im März um 1 Uhr UTC, also in der mitteleuropäischen Zeitzone von 2 Uhr MEZ auf 3 Uhr MESZ, statt.
Die Umstellung von der Sommer- auf die Normalzeit findet am letzten Sonntag im Oktober um 1 Uhr UTC, also in der mitteleuropäischen Zeitzone von 3 Uhr MESZ auf 2 Uhr MEZ, statt. |
Daran könntest du eine eventuelle Umstellung erkennen.
|
|
Kha
      
Beiträge: 3803
Erhaltene Danke: 176
Arch Linux
Python, C, C++ (vim)
|
Verfasst: Sa 20.11.10 14:48
*hust* UTC *hust* ?
Solche fürchterlichen Hacks solltest du also umgehen können, indem du die FileAge-Werte direkt vergleichst (ich gehe mal davon aus, dass Delphi die Umrechnung UTC->Local Time erst in FileDateToDateTime durchführt)  .
/edit: Aber wie das Problem überhaupt entstehen kann, wenn beide Dateien gleichzeitig abgefragt werden, kann ich auch nicht erklären.
_________________ >λ=
Zuletzt bearbeitet von Kha am Sa 20.11.10 16:27, insgesamt 1-mal bearbeitet
|
|
D. Annies 
      
Beiträge: 1843
windows 7
D6 Enterprise, D7 Pers und TD 2006
|
Verfasst: Sa 20.11.10 16:16
Und wie könnte es gehen?
Gruß, Detlef
_________________ ut vires desint, tamen est laudanda voluntas
|
|
Luckie
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: Sa 20.11.10 16:39
Was willst du machen? Wenn du prüfen willst, ob sich eine Datei geändert hat, ist ein Hash besser geeignet.
|
|
D. Annies 
      
Beiträge: 1843
windows 7
D6 Enterprise, D7 Pers und TD 2006
|
Verfasst: Sa 20.11.10 19:13
Hi, Luckie,
aha, ein Hash - klingt gut, aber nie gehört. Na, da brauche ich noch weitere Informationen
Gruß, Detlef
_________________ ut vires desint, tamen est laudanda voluntas
|
|
D. Annies 
      
Beiträge: 1843
windows 7
D6 Enterprise, D7 Pers und TD 2006
|
Verfasst: So 21.11.10 10:50
Ich habe es jetzt so gemacht:
Delphi-Quelltext 1: 2: 3:
| if (FileDateToDateTime(FileAge(work_filename)) <> FileDateToDateTime(FileAge(home_filename))) and (fileage(work_filename) + 3600 <> FileAge(home_filename)) and (fileage(work_filename) <> FileAge(home_filename) + 3600) then |
Was meint ihr dazu?
Gruß, Detlef
_________________ ut vires desint, tamen est laudanda voluntas
|
|
jaenicke
      
Beiträge: 19346
Erhaltene Danke: 1754
W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: So 21.11.10 11:14
Gibt es einen Grund warum du erstens teilweise ins Delphi-Datumsformat umwandelst und zweitens den Wert ständig wieder neu abfragst (also FileAge mehrfach für die selbe Datei aufrufst)?
Zudem ist FileAge veraltet und bringt zudem genau das genannte Problem mit der Sommerzeit mit sich, da du damit die Zeit explizit erst in die lokale Zeit umwandelst...
Nimm doch einfach FindFirstFile und benutze direkt ftLastWriteTime aus der entsprechenden TWin32FindData Struktur. Das ist erstens schneller und zweitens hast du dann direkt den UTC Zeitstempel, wenn es sich wie bereits geschrieben um ein NTFS Laufwerk handelt.
Eine Stunde sollte dabei 36.000.000.000 entsprechen (da der Zeitstempel die Anzahl der 100 Nanosekunden-Intervalle seit dem 01.01.1601 um 12 Uhr enthält).
|
|
D. Annies 
      
Beiträge: 1843
windows 7
D6 Enterprise, D7 Pers und TD 2006
|
Verfasst: So 21.11.10 15:12
Danke, Sebastian,
was ich gefunden habe ist der folgende Code:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47:
| procedure BuildFileList(aSourceDir, aDestDir: string; aSource, aFiles: TStringList; aMaxFileAge: Integer); cdecl; var sFileName, sSourceFileName: string; hSearch: THandle; rSourceFindData, rDestFindData: TWIN32FindData; ftCreationTime, ftLastWriteTime: TFileTime; begin aSourceDir := IncludeTrailingPathDelimiter(aSourceDir); aDestDir := IncludeTrailingPathDelimiter(aDestDir); aFiles.BeginUpdate; try for sFileName in aSource do begin sSourceFileName := aSourceDir + sFileName; hSearch := FindFirstFile(PChar(sSourceFileName), rSourceFindData); Windows.FindClose(hSearch); if (hSearch = INVALID_HANDLE_VALUE) or (rSourceFindData.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY <> 0) then Continue; hSearch := FindFirstFile(PChar(aDestDir + sFileName), rDestFindData); Windows.FindClose(hSearch); if hSearch = INVALID_HANDLE_VALUE then begin aFiles.Add(sSourceFileName); Continue; end; if aMaxFileAge = 0 then begin if UInt64(rSourceFindData.ftLastWriteTime) > UInt64(rDestFindData.ftLastWriteTime) then aFiles.Add(sSourceFileName); end else begin FileTimeToLocalFileTime(rSourceFindData.ftCreationTime, ftCreationTime); FileTimeToLocalFileTime(rSourceFindData.ftLastWriteTime, ftLastWriteTime); if (DaysBetween(FileTimeToDateTime(ftCreationTime), Date) <= aMaxFileAge) or (DaysBetween(FileTimeToDateTime(ftLastWriteTime), Date) <= aMaxFileAge) then aFiles.Add(sSourceFileName); end; end; aFiles.Sort; finally aFiles.EndUpdate; end; end; |
Da blick ich so nicht durch! Was ist dabei für mich überflüssig?
Wie gesagt, ich will ja nur speichern, wenn die Datei verändert wurde.
(Ich sehe auch nicht, dass ich fileage mehrfach für die gleiche Datei aufrufe.)
Gruß, Detlef
_________________ ut vires desint, tamen est laudanda voluntas
|
|
jaenicke
      
Beiträge: 19346
Erhaltene Danke: 1754
W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: So 21.11.10 15:15
|
|
D. Annies 
      
Beiträge: 1843
windows 7
D6 Enterprise, D7 Pers und TD 2006
|
Verfasst: So 21.11.10 15:52
ok, ok.
_________________ ut vires desint, tamen est laudanda voluntas
|
|
jaenicke
      
Beiträge: 19346
Erhaltene Danke: 1754
W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: So 21.11.10 15:56
So, hier einmal ein schnelles Beispiel, das direkt die Systemzeit benutzt und dementsprechend die UTC Zeit: 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46:
| function GetFileTime(const FileName: string): TFileTime; var SearchHandle: THandle; FindData: TWin32FindData; begin Result.dwLowDateTime := 0; Result.dwHighDateTime := 0; SearchHandle := FindFirstFile(PChar(FileName), FindData); if SearchHandle <> INVALID_HANDLE_VALUE then begin Windows.FindClose(SearchHandle); if (FindData.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY) = 0 then Result := FindData.ftLastWriteTime; end; end;
function IsFileOlder(const AFileName, AReferenceFileName: string): Boolean; var FileTime, ReferenceTime: TFileTime; begin FileTime := GetFileTime(AFileName); ReferenceTime := GetFileTime(AReferenceFileName); Result := FileTime.dwHighDateTime < ReferenceTime.dwHighDateTime; if not Result then Result := (FileTime.dwLowDateTime < ReferenceTime.dwLowDateTime) and (FileTime.dwHighDateTime = ReferenceTime.dwHighDateTime); end;
function IsFileOlderEx(const AFileName, AReferenceFileName: string; ADays: Int64 = 0; AHours: Int64 = 0; AMinutes: Int64 = 0; ASeconds: Int64 = 0): Boolean; var AllowedDiff: Int64; DiffLow, DiffHigh: Cardinal; FileTime, ReferenceTime: TFileTime; begin AllowedDiff := ((ADays * 24 + AHours) * 60 + AMinutes) * 60 + ASeconds; AllowedDiff := AllowedDiff * 10000000; DiffLow := AllowedDiff and $FFFFFFFF; DiffHigh := AllowedDiff shr 32; FileTime := GetFileTime(AFileName); ReferenceTime := GetFileTime(AReferenceFileName); Result := FileTime.dwHighDateTime + DiffHigh < ReferenceTime.dwHighDateTime; if not Result then Result := (FileTime.dwLowDateTime + DiffLow < ReferenceTime.dwLowDateTime) and (FileTime.dwHighDateTime + DiffHigh = ReferenceTime.dwHighDateTime); end; | Bei IsFileOlderEx kannst du auch eine minimale Differenz angeben, damit die Funktion True zurückgibt.
|
|
Gerd Kayser
      
Beiträge: 632
Erhaltene Danke: 121
Win 7 32-bit
Delphi 2006/XE
|
Verfasst: So 21.11.10 16:00
D. Annies hat folgendes geschrieben : | | Wie gesagt, ich will ja nur speichern, wenn die Datei verändert wurde. |
Und warum wertest Du dann nicht einfach das Archiv-Bit aus? Wenn Archiv-Bit gesetzt, dann die Datei kopieren und anschließend das Archiv-Bit entfernen.
|
|
D. Annies 
      
Beiträge: 1843
windows 7
D6 Enterprise, D7 Pers und TD 2006
|
Verfasst: So 21.11.10 16:55
@ Sebastian: Ich bin begeistert!
Jetzt muss ich mir nur noch überlegen, wie ich die Differenz von einer Stunde ausrechne, um dann nicht zu speichern.
@Gerd: Das wirkt viel leichter! Ich weiß nicht, wie man ein Archiv-Bit setzt/ändert.
LG an euch, Detlef
_________________ ut vires desint, tamen est laudanda voluntas
|
|
jaenicke
      
Beiträge: 19346
Erhaltene Danke: 1754
W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: So 21.11.10 17:07
D. Annies hat folgendes geschrieben : | | Jetzt muss ich mir nur noch überlegen, wie ich die Differenz von einer Stunde ausrechne, um dann nicht zu speichern. |
Es wird doch ohnehin die Weltzeit genommen, so dass die Sommerzeit usw. ohnehin keine Rolle spielt.
Und die Berechnung der Stunde (und Sekunden usw.) habe ich doch schon drin (in IsFileOlderEx). 
|
|
Luckie
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: So 21.11.10 17:18
Gerd Kayser hat folgendes geschrieben : | D. Annies hat folgendes geschrieben : | | Wie gesagt, ich will ja nur speichern, wenn die Datei verändert wurde. | Und warum wertest Du dann nicht einfach das Archiv-Bit aus? Wenn Archiv-Bit gesetzt, dann die Datei kopieren und anschließend das Archiv-Bit entfernen. |
Gefährlich, gefährlich. Nero setzt zum Beispiel beim Brennen das Archivbit zurück. Jetzt brenne ich Daten für meinen Kumpel, das Archivbit wird zurückgesetzt und schon sind sie beim nächsten Backup nicht mehr enthalten.
Und das mit dem letzten Änderungsdatum ist auch so eine Sache. Früher als man noch auf Disketten gespeichert hat, wurde beim Kopieren von der Diskette auf die Festplatte das Änderungsdatum auf das Datum zum Zeitpunkt des Kopierens gesetzt.
Wie gesagt, um zu entscheiden, ob sich eine Datei geändert hat, geht nur einigermaßen zuverlässig mittels eines direkten Vergleiches der Dateien. Und da hilft ein Hash.
|
|
D. Annies 
      
Beiträge: 1843
windows 7
D6 Enterprise, D7 Pers und TD 2006
|
Verfasst: So 21.11.10 18:02
@sebastian: Danke für deine erneuten Hinweise. Irgendwann blicke ich durch  )
@ Luckie: Ich finde nichts (brauchbares) über den Hash  (
Gruß, Detlef
_________________ ut vires desint, tamen est laudanda voluntas
|
|
jaenicke
      
Beiträge: 19346
Erhaltene Danke: 1754
W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: So 21.11.10 18:06
Es gibt diverse Hashfunktionen. Am sinnvollsten dürfte hier MD5 sein, da es relativ schnell geht und dennoch eine sehr geringe Kollisionswahrscheinlichkeit hat.
|
|
|