Autor Beitrag
D. Annies
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 1843

windows 7
D6 Enterprise, D7 Pers und TD 2006
BeitragVerfasst: 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:


ausblenden 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))

// and  ?????

 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
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 5284
Erhaltene Danke: 27

Win Vista (32), Win 7 (64)
Eclipse, SciTE, Lazarus
BeitragVerfasst: 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 1843

windows 7
D6 Enterprise, D7 Pers und TD 2006
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 5284
Erhaltene Danke: 27

Win Vista (32), Win 7 (64)
Eclipse, SciTE, Lazarus
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 3803
Erhaltene Danke: 176

Arch Linux
Python, C, C++ (vim)
BeitragVerfasst: Sa 20.11.10 14:48 
*hust* UTC *hust* ?
msdn.microsoft.com/e...90%28v=VS.85%29.aspx hat folgendes geschrieben:
The NTFS file system stores time values in UTC format, so they are not affected by changes in time zone or daylight saving time.
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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 1843

windows 7
D6 Enterprise, D7 Pers und TD 2006
BeitragVerfasst: 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



BeitragVerfasst: 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 1843

windows 7
D6 Enterprise, D7 Pers und TD 2006
BeitragVerfasst: 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 1843

windows 7
D6 Enterprise, D7 Pers und TD 2006
BeitragVerfasst: So 21.11.10 10:50 
Ich habe es jetzt so gemacht:

ausblenden 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) + 3600then


Was meint ihr dazu?
Gruß, Detlef

_________________
ut vires desint, tamen est laudanda voluntas
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19346
Erhaltene Danke: 1754

W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 1843

windows 7
D6 Enterprise, D7 Pers und TD 2006
BeitragVerfasst: So 21.11.10 15:12 
Danke, Sebastian,

was ich gefunden habe ist der folgende Code:

ausblenden volle Höhe Delphi-Quelltext
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                                             // Welche Units soll ich einbinden?
  sFileName, sSourceFileName: string;
  hSearch: THandle;
  rSourceFindData, rDestFindData: TWIN32FindData;
  ftCreationTime, ftLastWriteTime: TFileTime;
begin
  // einmal reicht ... muß ja nicht bei jeder Datei einzeln
  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 <> 0then
        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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19346
Erhaltene Danke: 1754

W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: So 21.11.10 15:15 
user profile iconD. Annies hat folgendes geschrieben Zum zitierten Posting springen:
(Ich sehe auch nicht, dass ich fileage mehrfach für die gleiche Datei aufrufe.)
Beispiel für die erste der beiden Dateien:
user profile iconD. Annies hat folgendes geschrieben Zum zitierten Posting springen:
ausblenden 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) + 3600then
3 Aufrufe ;-)
D. Annies Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 1843

windows 7
D6 Enterprise, D7 Pers und TD 2006
BeitragVerfasst: So 21.11.10 15:52 
ok, ok.

_________________
ut vires desint, tamen est laudanda voluntas
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19346
Erhaltene Danke: 1754

W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: So 21.11.10 15:56 
So, hier einmal ein schnelles Beispiel, das direkt die Systemzeit benutzt und dementsprechend die UTC Zeit:
ausblenden volle Höhe Delphi-Quelltext
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
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 632
Erhaltene Danke: 121

Win 7 32-bit
Delphi 2006/XE
BeitragVerfasst: So 21.11.10 16:00 
user profile iconD. Annies hat folgendes geschrieben Zum zitierten Posting springen:
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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 1843

windows 7
D6 Enterprise, D7 Pers und TD 2006
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19346
Erhaltene Danke: 1754

W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: So 21.11.10 17:07 
user profile iconD. Annies hat folgendes geschrieben Zum zitierten Posting springen:
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



BeitragVerfasst: So 21.11.10 17:18 
user profile iconGerd Kayser hat folgendes geschrieben Zum zitierten Posting springen:
user profile iconD. Annies hat folgendes geschrieben Zum zitierten Posting springen:
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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 1843

windows 7
D6 Enterprise, D7 Pers und TD 2006
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19346
Erhaltene Danke: 1754

W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: 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.