Witam,
Jestem tu nowy. Kiedyś (jeszcze za czasów DOS-a) trochę programowałem w Turbo Pascalu. Teraz, na stare lata trochę mi odbiło i postanowiłem spróbować wrócić do pisania programów. Tym razem korzystam z Lazarusa.
Chcę spróbować napisać własny program pod Windows do robienia backupu plików, bo nie znalazłem do tej pory programu spełniającego moje wymagania.
Na razie walczę z kopiowaniem plików (żeby to było szybkie chcę korzystać z procedur blockread i blockwrite, docelowo chcę zapis i odczyt dać w dwóch wątkach, żeby jednocześnie dało się odczytywać dane z dysku źródłowego i zapisywać na docelowym). Jednak mam problem, którego nie potrafię na razie rozwiązać. Chodzi o to, że odczytując plik mimowolnie zmieniam jego czas ostatniego dostępu.
Znalazłem informację, że w celu zachowania oryginalnego czasu dostępu należy natychmiast po otwarciu pliku użyć funkcji SetFileTime z czasem ostatniego dostępu wynoszącym $0FFFFFFFF, $0FFFFFFFF. Link do artykułu z wyjaśnieniem: link.
Jednak mam pewien problem. Do odczytu pliku źródłowego przez BlockRead otwieram go procedurą Reset. Przed tą procedurą wykonuję oczywiście AssignFile(source,NazwaPlikuZrodlowego). Jednak do użycia funkcji SetFileTime powinienem użyć filehandle:=FileOpen(PlikDocelowy, fmOpenReadWrite or fmShareExclusive). Nie wiem, jak to pogodzić. Czy ktoś z Was mógłby mnie w tym temacie oświecić?
Poniżej zamieszczam kompletną procedurę kopiowania pliku z mojego programu (jest to moja aktualna wersja robocza):
procedure KopiujPlik;
var
fileHandle : cardinal;
fsCreationTime : TFileTime;
fsLastAccessTime : TFileTime;
fsLastModificationTime: TFileTime;
CzasStartu,CzasPracy:TDateTime;
CzasPracyString,OldCzasPracyString:string;
SourceFile,TargetFile:file;
cntRead,cntWrite:word;
Buffer:array[0..511] of byte;
SizeOfFile,Skopiowano,temp:Int64;
PromilPostepu,LastPromilPostepu:Integer;
atrybuty,DataPliku:LongInt;
begin
CzasStartu:=now;
OldCzasPracyString:='0';
CzasPracy:=0;
Skopiowano:=0;
PromilPostepu:=0;
LastPromilPostepu:=-1;
FileMode:=0;
AssignFile (SourceFile,NazwaPliku);
{ filehandle:=FileOpen(NazwaPliku, fmOpenReadWrite or fmShareExclusive);
fsLastAccessTime.dwHighDateTime:=$0FFFFFFFF;
fsLastAccessTime.dwLowDateTime:=$0FFFFFFFF;}
Reset(SourceFile,1);
{ SetFileTime(fileHandle, nil, @fsLastAccessTime, nil);
CloseHandle(fileHandle);}
AssignFile (TargetFile,PlikDocelowy);
Rewrite(TargetFile,1);
SizeOfFile:=FileSize(SourceFile);
repeat
BlockRead(SourceFile,Buffer,SizeOf(Buffer),cntRead);
BlockWrite(TargetFile,Buffer,cntRead,cntWrite);
Skopiowano:=Skopiowano+cntWrite;
temp:=Skopiowano*1000 div SizeOfFile;
PromilPostepu:=temp;
if(LastPromilPostepu<>PromilPostepu) then
begin
ProgressBar1.Position:=PromilPostepu;
LastPromilPostepu:=PromilPostepu;
CzasPracy:=now-CzasStartu;
CzasPracyString:=FormatDateTime('hh:nn:ss',CzasPracy);
if(CzasPracyString<>OldCzasPracyString) then
begin
Czasomierz.Caption:=CzasPracyString;
Refresh;
OldCzasPracyString:=CzasPracyString;
end;
end;
until (cntRead=0) or (CntWrite<>cntRead);
CloseFile(SourceFile);
CloseFile(TargetFile);
fileHandle:=CreateFile(PChar(NazwaPliku), GENERIC_READ, FILE_SHARE_READ, nil, OPEN_EXISTING, 0, 0);
GetFileTime(fileHandle, @fsCreationTime, @fsLastAccessTime, @fsLastModificationTime);
{ DataPliku:=FileAge(NazwaPliku);
FileSetDate(PlikDocelowy,DataPliku);}
CloseHandle(fileHandle);
{ fileHandle:=CreateFile(PChar(PlikDocelowy), GENERIC_READ, FILE_SHARE_READ, nil, OPEN_EXISTING, 0, 0);}
filehandle:=FileOpen(PlikDocelowy, fmOpenReadWrite or fmShareExclusive);
SetFileTime(fileHandle, @fsCreationTime, @fsLastAccessTime, @fsLastModificationTime);
{ SetFileTime(fileHandle, @fsCreationTime, nil, nil);
SetFileTime(fileHandle, nil, @fsLastAccessTime, nil);
SetFileTime(fileHandle, nil, nil, @fsLastModificationTime);}
{ SetFileTime(fileHandle, @fsLastModificationTime, @fsLastModificationTime, @fsLastModificationTime);}
CloseHandle(fileHandle);
atrybuty:=FileGetAttr(NazwaPliku);
{ FileSetAttr(PlikDocelowy,atrybuty);}
CzasPracy:=now-CzasStartu;
Czasomierz.Caption:=FormatDateTime('hh:nn:ss',CzasPracy);
end;