type
TFileOverwriteMode = (fomAlways, fomIfNewer, fomIfOlder, fomIfSameDate);
TFileCopyCallback = procedure(ProgressValue: int64) of object;
function RF_SetAllFileDates(FName: string;
aCreation,
aLastAccess,
aLastWrite : TDateTime): boolean;
var
aHandle: integer;
FT1, FT2, FT3: TFileTime;
locFT1, locFT2, locFT3: TFileTime;
ST1, ST2, ST3 : TSystemTime;
begin
aHandle := FileOpen(FName, fmOpenWrite or fmShareDenyWrite);
Result := aHandle >= 0;
if Result then
try
DateTimeToSystemTime(aCreation,ST1);
DateTimeToSystemTime(aLastAccess,ST2);
DateTimeToSystemTime(aLastWrite,ST3);
SystemTimeToFileTime(ST1,FT1);
SystemTimeToFileTime(ST2,FT2);
SystemTimeToFileTime(ST3,FT3);
LocalFileTimeToFileTime(FT1,locFT1);
LocalFileTimeToFileTime(FT2,locFT2);
LocalFileTimeToFileTime(FT3,locFT3);
SetFileTime(aHandle,@locFT1, @locFT2, @locFT3);
finally
FileClose(aHandle);
end;
end;
function RF_CopyFile(SourceName, DestName: string;
CopyMode: TFileOverwriteMode;
Progress: TFileCopyCallback): boolean;
var
BytesRead,BytesToRead, P, Percent: Int64;
SourceStream, DestStream: TFileStream;
SourceDateTime, DestDateTime: TDateTime;
Execute: boolean;
begin
Result := false;
if not FileExists(SourceName) then exit;
if not FileAge(SourceName, SourceDateTime) then exit;
Execute:= true;
BytesRead := 0;
Percent := 0;
P := 0;
{-DestName darf auch ein Directory sein...dann den Dateinamen ran hängen}
if DirectoryExists(DestName)
then DestName := IncludeTrailingBackslash(DestName)+ExtractFileName(SourceName);
if FileExists(DestName) then begin
if not FileAge(DestName, DestDateTime) then exit;
case CopyMode of
fomAlways : ;
fomIfNewer : Execute := DestDateTime > SourceDateTime;
fomIfOlder : Execute := DestDateTime < SourceDateTime;
fomIfSameDate : Execute := Trunc(DestDateTime) = Trunc(SourceDateTime);
end;
end;
if not Execute then exit;
SourceStream := TFileStream.Create(SourceName,fmOpenRead or fmShareDenyNone);
DestStream := TFileStream.Create(DestName,fmCreate);
try
if @Progress = nil then begin // so geht es am schnellsten
DestStream.CopyFrom(SourceStream,SourceStream.Size);
Result := true; // was soll noch schiefgehen ??
end else begin // mit Fortschrittanzeige
Progress(Percent);
BytesToRead := SizeOf(StreamCopyBuffer);
if SourceStream.Size < BytesToRead then BytesToRead := SourceStream.Size;
repeat
SourceStream.ReadBuffer(StreamCopyBuffer,BytesToRead);
DestStream.WriteBuffer(StreamCopyBuffer,BytesToRead);
BytesRead := BytesRead + BytesToRead;
Percent := (BytesRead * 100) div SourceStream.Size;
if P <> Percent then begin
Progress(Percent);
P := Percent;
end;
if (SourceStream.Size - BytesRead) <= BytesToRead
then BytesToRead := SourceStream.Size - BytesRead;
until BytesRead >= SourceStream.Size;
Result := BytesRead = SourceStream.SIZE;
end;
finally
SourceStream.Free;
DestStream.Free;
end;
if Result then RF_SetAllFileDates(DestName, SourceDateTime, SourceDateTime, SourceDateTime);
end;