Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   Dateidatum, Dateien vergleichen und Kopieren (https://www.delphipraxis.net/199694-dateidatum-dateien-vergleichen-und-kopieren.html)

Grisu2000 12. Feb 2019 18:03

Dateidatum, Dateien vergleichen und Kopieren
 
Hallo,
ich versuche zwei Dateien zu vergleichen (Zeitstempel) und dann entweder von USB-Stick auf Festplatte oder von Festplatte auf USB zu kopieren.
Ist die Datei nur auf einem Medium vorhanden funktioniert das Kopieren in beide Richtungen.
Ist auf beiden Medien (Festplatte und USB) die Datei vorhanden funktioniert das Überschreiben nur von USB auf Festplatte. Beim Überschreiben von Festplatte auf USB gibt es einen Zeitversatz bei den Zeitstempeln von 2 Sekunden, d.h. nach dem Überschreiben ist die Datei auf dem USB-Stick neuer als auf der Festplatte.
Ich könnte natürlich jetzt erst die Datei löschen und dann neu Schreiben, mich würde aber interessieren, ob es anstatt FileAge oder CopyFile bessere Befehle gibt, damit die Dateien nach einem Kopiervorgang wirklich gleich sind :?:.

Hier der Codeteil, den ich dafür benutze:
Delphi-Quellcode:
FileAge(Datei1,Datum1,true);
FileAge(Datei1USB,Datum2,true);
if Datum1>Datum2 then
   copyfile(PChar(Datei1),PChar(Datei1USB),false);
if Datum1<Datum2 then
   copyfile(PChar(Datei1USB),PChar(Datei1),false);

Danke und Gruß
Hanns-Dieter

hoika 12. Feb 2019 18:20

AW: Dateidatum, Dateien vergleichen und Kopieren
 
Hallo,
setz doch nach dem Kopieren das Datum noch mal neu (SetFileAge).

Jasocul 12. Feb 2019 19:57

AW: Dateidatum, Dateien vergleichen und Kopieren
 
Hallo,

ich nutze zum Vergleich TFile.GetLastWriteTime, da ich früher mit ähnlichen Problemen zu tun hatte.
Da es sich um TDateTime-Werte handelt, lasse ich aber dennoch eine gewisse Toleranz beim Vergleich zu. Die liegen allerdings im Millisekunden-Bereich.

Grisu2000 12. Feb 2019 23:47

AW: Dateidatum, Dateien vergleichen und Kopieren
 
Danke schon mal für die schnelle Antwort. Wie machst Du das mit der Toleranz? Hast Du das ein Beispiel für mich?

Jasocul 13. Feb 2019 06:42

AW: Dateidatum, Dateien vergleichen und Kopieren
 
TDateTime sind intern Float-Werte.

Da ich das in einer alten Anwendung nutze, ziehe ich einfach die beiden Werte voneinander ab und prüfe, ob der Absolut-Wert kleiner 0.0001 ist.

Man kann aber auch die "neue" Funktion IsZero dafür nutzen. Entweder gab es die bei meiner damaligen Umstellung noch nicht oder ich wusste nicht, dass es die schon gab. Sonst hätte ich die dafür verwendet.

Andreas L. 13. Feb 2019 08:29

AW: Dateidatum, Dateien vergleichen und Kopieren
 
Du kannst (z. B. mit dem DEC) Hashes erstellen (z. B. MD5) und damit die Dateien vergleichen. Sind die beiden Dateien identisch ist auch der Hash 100%ig gleich. Ich denke das ist besser als FileAge zu verwenden.

Klaus01 13. Feb 2019 08:31

AW: Dateidatum, Dateien vergleichen und Kopieren
 
.. bleibt dann nur die Frage welche Datei dann aktueller ist.
Nur am Hash wird man dies nicht erkennen können.

Grüße
Klaus

Moombas 13. Feb 2019 08:31

AW: Dateidatum, Dateien vergleichen und Kopieren
 
Ich nutze die Version von DelphiTreff:
Delphi-Quellcode:
function GetFileVersion(Path: string): string;
var
  lpVerInfo: pointer;
  rVerValue: PVSFixedFileInfo;
  dwInfoSize: cardinal;
  dwValueSize: cardinal;
  dwDummy: cardinal;
  lpstrPath: pchar;

begin
  if Trim(Path) = EmptyStr then
    lpstrPath := pchar(ParamStr(0))
  else
    lpstrPath := pchar(Path);

  dwInfoSize := GetFileVersionInfoSize(lpstrPath, dwDummy);

  if dwInfoSize = 0 then
  begin
    Result := 'No version specification';
    Exit;
  end;

  GetMem(lpVerInfo, dwInfoSize);
  GetFileVersionInfo(lpstrPath, 0, dwInfoSize, lpVerInfo);
  VerQueryValue(lpVerInfo, '', pointer(rVerValue), dwValueSize);

  with rVerValue^ do
  begin
    Result := IntTostr(dwFileVersionMS shr 16);
    Result := Result + '.' + IntTostr(dwFileVersionMS and $FFFF);
    Result := Result + '.' + IntTostr(dwFileVersionLS shr 16);
    Result := Result + '.' + IntTostr(dwFileVersionLS and $FFFF);
  end;
  FreeMem(lpVerInfo, dwInfoSize);

end; {function GetFileVersion() ...}
Aufgerufen wird diese dann:

Delphi-Quellcode:
variable1 := GetFileVersion('USB.exe');
variable2 := GetFileVersion('HDD.exe');
Und was die Auswertung angeht, kommt es auf den Aufbau der Versionsnummer an. Gehe ich von dem gleichen Aufbau wie in Delphi aus, wäre eine Möglichkeit die Dateiversion in teilen zu prüfen. Dabei würde ich wie folgt vorgehen:

1. Die Dateiversionen nach '.' durchsuchen und zählen (= Anzahl der zu prüfenden Zahlen + 1; evtl. Vergleichen ob beide Versionsnummern die gleiche Anzahl haben!) z.B.(Herkunft weiß ich nicht mehr^^):
Delphi-Quellcode:
function Split(text: string; delimiter: char; p: integer): string;
var
  stl: TStrings;
begin
  stl := TStringList.Create;
  try
    stl.delimiter := delimiter;
    stl.DelimitedText := text;
  finally
    result := stl.Strings[p];
    stl.free;
  end;
end;
Aufruf:
Delphi-Quellcode:
split(String, '.', Teil);

2. Die entsprechenden Teile mit einander vergleichen, von vorne nach hinten.
3. Sobald sie unterschiedlich sind, prüfen welche größer ist und die Vergleichs-Schleife verlassen.
4. Kopiervorgang abhängig der letzten Prüfung einleiten.

p80286 13. Feb 2019 09:11

AW: Dateidatum, Dateien vergleichen und Kopieren
 
Zitat:

Zitat von Klaus01 (Beitrag 1425402)
.. bleibt dann nur die Frage welche Datei dann aktueller ist.
Nur am Hash wird man dies nicht erkennen können.

Korrekt! Nutzt Du den USB-Stick als Backup, sollte die Festplatte das führende Medium sein.
Wenn aber der Stick für den Datenaustasch "onthefly" genutzt wird,hilft nur die Beurteilung durch den Nutzer.Aber alle gleichen Dateien fallen dann schon einmal weg.

Gruß
K-H

Schokohase 13. Feb 2019 09:25

AW: Dateidatum, Dateien vergleichen und Kopieren
 
@Moombas

Ja, aber nur wenn es sich um Dateien handelt, die auch diese Versionsinformationen in sich tragen, was ich hier bezweifeln möchte

Moombas 13. Feb 2019 09:45

AW: Dateidatum, Dateien vergleichen und Kopieren
 
Ok, wenn es wirklich nur über den Zeitstempel geht:

Ich nutze bei mir (Updater) die Copyfile funktion zum kopieren von Dateien. Habe da nie drauf geachtet und daher eben mal getestet. Er kopiert bei mir die Datei 1:1 incl. Änderungsdatum. (Datei wurde 10:41 das letzte mal geändert - um 10:42 kopiert - neue Datei Hat als Änderungsdatum 10:41, kopiert wurde von lokaler HDD auf Server HDD)

Da kommt mir die Frage auf welche Zeitstempel verglichen werden, wenn du das Änderungsdatum (nicht das Erstelldatum!) vergleichst, müsste deine Prüfung nach Zeit normalerweise passen.

Folgende Funktion würde dir das Änderungsdatum ausgeben;
Delphi-Quellcode:
function ReportFileTimes(const FileName: string) : TDateTime;

  procedure ReportTime(const Name: string; const FileTime: TFileTime);
  var
    SystemTime, LocalTime: TSystemTime;
  begin
    if not FileTimeToSystemTime(FileTime, SystemTime) then
      RaiseLastOSError;
    if not SystemTimeToTzSpecificLocalTime(nil, SystemTime, LocalTime) then
      RaiseLastOSError;
    result:=SystemTimeToDateTime(LocalTime);
  end;

var
  fad: TWin32FileAttributeData;
begin
  if not GetFileAttributesEx(PChar(FileName), GetFileExInfoStandard, @fad) then
    RaiseLastOSError;
  ReportTime('Modified', fad.ftLastWriteTime);
end;

Schokohase 13. Feb 2019 10:18

AW: Dateidatum, Dateien vergleichen und Kopieren
 
Das Verhalten liegt an NTFS (Festplatte) vs. FAT32 (USB-Stick).

Hier ein kleiner Test, wo man immer eine Differenz von 1-2 Sekunden sieht, obwohl die Werte exakt gleich sein müssten (siehe den unteren Teil, wo der Wert explizit bei beiden gleich gesetzt wird).
Delphi-Quellcode:
program FileAgeTest;

{$APPTYPE CONSOLE}
{$R *.res}

uses
  System.SysUtils,
  System.IOUtils;

procedure Main;
const
  NTFSVolume = 'E:\'; // muss ein NTFS-Laufwerk sein
  FAT32Volume = 'F:\'; // muss ein FAT32-Laufwerk sein
  FileName = 'TestFile.txt';
var
  LastWrite: TDateTime;
begin
  if TFile.Exists(TPath.Combine(NTFSVolume, FileName)) then
    TFile.Delete(TPath.Combine(NTFSVolume, FileName));
  if TFile.Exists(TPath.Combine(FAT32Volume, FileName)) then
    TFile.Delete(TPath.Combine(FAT32Volume, FileName));

  TFile.WriteAllText(TPath.Combine(NTFSVolume, FileName), 'test');
  Writeln(DateTimeToStr(TFile.GetLastWriteTime(TPath.Combine(NTFSVolume, FileName))));
  TFile.Copy(TPath.Combine(NTFSVolume, FileName),TPath.Combine(FAT32Volume, FileName));
  Writeln(DateTimeToStr(TFile.GetLastWriteTime(TPath.Combine(FAT32Volume, FileName))));

  LastWrite := System.SysUtils.Now;

  TFile.SetLastWriteTime(TPath.Combine(NTFSVolume, FileName),LastWrite);
  TFile.SetLastWriteTime(TPath.Combine(FAT32Volume, FileName),LastWrite);

  Writeln(DateTimeToStr(TFile.GetLastWriteTime(TPath.Combine(NTFSVolume, FileName))));
  Writeln(DateTimeToStr(TFile.GetLastWriteTime(TPath.Combine(FAT32Volume, FileName))));
end;

begin
  try
    Main;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
  Readln;

end.

dummzeuch 13. Feb 2019 11:08

AW: Dateidatum, Dateien vergleichen und Kopieren
 
FAT kann die Zeit nur mit einer Auflösung von 2 Sekunden speichern (Bit 0 wird weggelassen), NTFS ist da genauer.

Andreas L. 13. Feb 2019 11:27

AW: Dateidatum, Dateien vergleichen und Kopieren
 
Zitat:

Zitat von Klaus01 (Beitrag 1425402)
.. bleibt dann nur die Frage welche Datei dann aktueller ist.
Nur am Hash wird man dies nicht erkennen können.

Du kannst mit der Windows API feststellen wenn sich eine Datei ändert: SHChangeNotifyEntry, SHChangeNotifyRegister.

Es gibt auch Delphi Implementationen z. B. TJvChangeNotify aus der JVCL (Download). Aus die schnelle habe ich noch die Unit DirWatch von Angus Johnson gefunden.

Natürlich kannst du das auch selbst schreiben. z. B. einen Thread erstellen der (ggf. in bestimmten Intervallen) den Hash einer oder mehrerer Dateien erstellt. Hat sich der Hash seit dem letzten Durchlauf geändert weißt du das die Datei geändert wurde. Dann musst du nur noch via Synchronize (wichtig!) ein Event aufrufen und schon kann dein Programm darauf reagieren und die Datei kopieren. Aber Achtung: Wenn der Thread während dem kopieren weiter läuft, wird er natürlich die kopierte Datei ebenfalls als geändert betrachten. Evtl. den Thread einfach mitteilen das die Datei zwar geändert wurde, der Thread aber diese "Änderung" bis zur "richtigen Änderung" ignorieren soll. Aber es gibt bestimmt auch noch andere Wege. Gut am Thread ist das dein Programm nicht einfriert und weiter benutzt werden kann.

Schokohase 13. Feb 2019 11:34

AW: Dateidatum, Dateien vergleichen und Kopieren
 
Zitat:

Zitat von Andreas L. (Beitrag 1425418)
Du kannst mit der Windows API feststellen wenn sich eine Datei ändert: SHChangeNotifyEntry, SHChangeNotifyRegister.

Bei so einem USB-Stick denke ich auch immer daran, dass der mobil ist, also auch nicht am Rechner angeschlossen ist, oder sogar an einem anderen Rechner und dort andere Dateien aufgespielt bekommt.

Moombas 13. Feb 2019 11:51

AW: Dateidatum, Dateien vergleichen und Kopieren
 
Betrifft es auch das Änderungsdatum wegen dem Zeitunterschied (NTFS <> Fat32), insbesondere wenn die Datei ggf. das Datum schon beinhaltet hat?

Grisu2000 13. Feb 2019 17:20

AW: Dateidatum, Dateien vergleichen und Kopieren
 
Es gibt keine Versionsnummer in der Datei.
Mit der Version von Jasocul mit GetLastWriteTime funktioniert es wie ich es brauche.
Aber mit den anderen Beispielen hab ich auch schon wieder viel gelernt.

Danke an Alle!!!

Grisu2000 14. Feb 2019 19:08

AW: Dateidatum, Dateien vergleichen und Kopieren
 
Es gibt keine Versionsnummer in der Datei.
Mit der Version von Jasocul mit GetLastWriteTime funktioniert es wie ich es brauche.
Aber mit den anderen Beispielen hab ich auch schon wieder viel gelernt.

Danke an Alle!!!


Alle Zeitangaben in WEZ +1. Es ist jetzt 05:56 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