Delphi FileSetDate是错误的

时间:2016-06-23 18:29:56

标签: delphi filesystems delphi-xe8

我想修改文件的更新日期。所以我使用以下代码来完成它。

procedure FileDateUpdate;
var
  date1,date2 : TDateTime;
  file1, file2 : string;
begin
  file1 := 'G:\ab.pdf';
  file2 := 'G:\Shirish\ab.pdf';
  FileAge( file1, date1);
  FileSetDate( file2, DateTimeToFileDate(date1) );
  Fileage( file2, date2);
  ShowMessage('File1 date: '+ DateTimeToStr(date1) + '|| File2 date: '+ DateTimeToStr(date2));
end;

输出

File1 date: 24-05-2016 11:34:35|| File2 date: 24-05-2016 11:34:34

有趣的是,两个文件的日期永远不会相同。

如果我使用弃用的方法FileAge,它可以正常工作

i := FileAge(file1);
FileSetDate(file2, i);
j := FileAge(file2);
ShowMessage('File1 date: '+ DateTimeToStr(FileDateToDateTime(i)) + '|| File2 date: '+ DateTimeToStr(FileDateToDateTime(j)));

输出

File1 date: 24-05-2016 11:34:36|| File2 date: 24-05-2016 11:34:36

1 个答案:

答案 0 :(得分:0)

随着时间的推移,我从www收集了一些单位的功能。 (我不记得我是否改变了其中一些)。

也许这对机会有帮助 (我用它来改变" Puvananthiran delphi记事本"  用于更新根据上次修改日期加载的文件。)

unit FileTimeUtils;

interface

uses
  SysUtils, Windows;

function DateTimeToFileTime(const aDt: TDateTime): TFileTime;
function FileTimeToDateTime(ft: TFileTime): TDateTime;

procedure DaDateTimeToFileTime(const aDt: TDateTime; var aFileTime: TFileTime);
procedure DaFileTimeToDateTime(ft: TFileTime; var aDateTime: TDateTime);

function FindLastWrittenFile(const aDir, aSearch: String): String;
function GetFileDateTime(const aFileName: String; var aCreationTime, aLastAccessTime, aLastModificationTime: TDateTime): Boolean;
function SetFileDateTime(const aFileName: String; aNewCreationTime, aNewAccessTime, aNewModifyTime: TDateTime): Boolean;

function GetCreationTime(const aFileName: String): TDateTime;
function GetLastAccessTime(const aFileName: String): TDateTime;
function GetLastWriteTime(const aFileName: String): TDateTime;

function SetCreationTime(const aFileName: String; aNewCreationTime: TDateTime): Boolean;
function SetLastAccessTime(const aFileName: String; aNewAccessTime: TDateTime): Boolean;
function SetLastWriteTime(const aFileName: String; aNewModifyTime: TDateTime): Boolean;

implementation


function DateTimeToFileTime(const aDt: TDateTime): TFileTime;
var
  st: TSystemTime;
begin
  DateTimeToSystemTime(aDt, st);
  if not (SystemTimeToFileTime(st, Result) and LocalFileTimeToFileTime(Result, Result)) then
    RaiseLastOSError
end;


function FileTimeToDateTime(ft: TFileTime): TDateTime;
var
  st: TSystemTime;
begin
  if not (FileTimeToLocalFileTime(ft, ft) and FileTimeToSystemTime(ft, st)) then
    RaiseLastOSError;
  Result:= SystemTimeToDateTime(st)
end;


procedure DaDateTimeToFileTime(const aDt: TDateTime; var aFileTime: TFileTime);
begin
  aFileTime:= DateTimeToFileTime(aDt)
end;


procedure DaFileTimeToDateTime(ft: TFileTime; var aDateTime: TDateTime);
begin
  aDateTime:= FileTimeToDateTime(ft)
end;


function FindLastWrittenFile(const aDir, aSearch: String): String;
var
  Dir: String;
  vR:  TSearchRec;
  LastWrite, LastWriteAllFiles: TDateTime;
begin
  {$Warnings Off}
  Dir:= IncludeTrailingBackslash(aDir);
  LastWriteAllFiles:= 0;
  Result:= '';
  if FindFirst(Dir + aSearch, faAnyFile - faDirectory, vR) = 0 then
    repeat
      LastWrite:= FileTimeToDateTime(vR.FindData.ftLastWriteTime);
      {$Warnings On}
      if LastWrite > LastWriteAllFiles then
      begin
        LastWriteAllFiles:= LastWrite;
        Result:= vR.Name
      end
    until FindNext(vR) <> 0;
  SysUtils.FindClose(vR)
end;


function GetFileDateTime(const aFileName: String; var aCreationTime, aLastAccessTime, aLastModificationTime: TDateTime): Boolean;
var
  FileHandle: Cardinal;
  CreationTime, LastAccessTime, LastWriteTime: TFileTime;
begin
  Result:= False;
  FileHandle:= CreateFile(PChar(aFileName), GENERIC_READ, FILE_SHARE_READ, nil, OPEN_EXISTING, 0, 0);
  if FileHandle <> INVALID_HANDLE_VALUE then
    try
      Result:= GetFileTime(FileHandle, @CreationTime, @LastAccessTime, @LastWriteTime);
      DaFileTimeToDateTime(CreationTime, aCreationTime);
      DaFileTimeToDateTime(LastAccessTime, aLastAccessTime);
      DaFileTimeToDateTime(LastWriteTime, aLastModificationTime)
    finally
      CloseHandle(FileHandle)
    end
end; { GetFileDateTime }


function SetFileDateTime(const aFileName: String; aNewCreationTime, aNewAccessTime, aNewModifyTime: TDateTime): Boolean;
var
  FileHandle: Cardinal;
  CreationTime, LastAccessTime, LastWriteTime: TFileTime;
begin
  Result:= False;

  CreationTime := DateTimeToFileTime(aNewCreationTime);
  LastAccessTime:= DateTimeToFileTime(aNewAccessTime);
  LastWriteTime:= DateTimeToFileTime(aNewModifyTime);

  FileHandle:= FileOpen(aFileName, fmOpenReadWrite or fmShareExclusive);
  try
    if SetFileTime(FileHandle, @CreationTime, @LastAccessTime, @LastWriteTime) then
      Result:= True
  finally
    FileClose(FileHandle)
  end
end; { SetFileDateTime }


function GetCreationTime(const aFileName: String): TDateTime;
var
  ffd: TWin32FindData;
  dft: DWord;
  LFT: TFileTime;
  h: THandle;
begin
  Result:= 0;
  h:= Windows.FindFirstFile(PChar(aFileName), ffd);
  if INVALID_HANDLE_VALUE <> h then
  begin
    Windows.FindClose(h);
    FileTimeToLocalFileTime(ffd.ftCreationTime, LFT);
    FileTimeToDosDateTime(LFT, LongRec(dft).Hi, LongRec(dft).Lo);
    Result:= FileDateToDateTime(dft)
  end
end;


{------------------------------------------------------------------------------
  "GetLastAccessTime()" will return a given file's last access time
  as a Delphi "TDateTime" type which you can convert to a string by using the
  "DateTimeToStr()" function. For example:

  MessageDlg('c:config.sys was last accessed on ' +
    DateTimeToStr( GetLastAccessTime( 'c:config.sys' ) ),
    mtInformation, [mbOk], 0 );
------------------------------------------------------------------------------}

function GetLastAccessTime(const aFileName: String): TDateTime;
var
  ffd: TWin32FindData;
  dft: DWord;
  LFT: TFileTime;
  h: THandle;
begin
  Result:= 0;
  // get file information
  h:= Windows.FindFirstFile(PChar(aFileName), ffd);
  if INVALID_HANDLE_VALUE <> h then
  begin

    // we're looking for just one file,
    // so close our "find"
    Windows.FindClose(h);

    // convert the FILETIME to
    // local FILETIME
    FileTimeToLocalFileTime(ffd.ftLastAccessTime, LFT);

    // convert FILETIME to
    // DOS time
    FileTimeToDosDateTime(LFT, LongRec(dft).Hi, LongRec(dft).Lo);

    // finally, convert DOS time to
    // TDateTime for use in Delphi's
    // native date/time functions
    Result:= FileDateToDateTime(dft)
  end
end;


function GetLastWriteTime(const aFileName: String): TDateTime;
var
  ffd: TWin32FindData;
  dft: DWord;
  LFT: TFileTime;
  h: THandle;
begin
  Result:= 0;
  h:= Windows.FindFirstFile(PChar(aFileName), ffd);
  if INVALID_HANDLE_VALUE <> h then
  begin
    Windows.FindClose(h);
    FileTimeToLocalFileTime(ffd.ftLastWriteTime, LFT);
    FileTimeToDosDateTime(LFT, LongRec(dft).Hi, LongRec(dft).Lo);
    Result:= FileDateToDateTime(dft)
  end
end;


function SetCreationTime(const aFileName: String; aNewCreationTime: TDateTime): Boolean;
var
  FileHandle: Cardinal;
  CreationTime, LastAccessTime, LastWriteTime: TDateTime;
  ftCreationTime, ftLastAccessTime, ftLastWriteTime: TFileTime;
begin
  Result:= False;
  if not GetFileDateTime(aFileName, CreationTime, LastAccessTime, LastWriteTime) then
    Exit;

  ftCreationTime := DateTimeToFileTime(aNewCreationTime);
  ftLastAccessTime:= DateTimeToFileTime(LastAccessTime);
  ftLastWriteTime:= DateTimeToFileTime(LastWriteTime);

  FileHandle:= FileOpen(aFileName, fmOpenReadWrite or fmShareExclusive);
  try
    if SetFileTime(FileHandle, @ftCreationTime, @ftLastAccessTime, @ftLastWriteTime) then
      Result:= True
  finally
    FileClose(FileHandle)
  end
end; { SetCreationTime }


function SetLastAccessTime(const aFileName: String; aNewAccessTime: TDateTime): Boolean;
var
  FileHandle: Cardinal;
  CreationTime, LastAccessTime, LastWriteTime: TDateTime;
  ftCreationTime, ftLastAccessTime, ftLastWriteTime: TFileTime;
begin
  Result:= False;
  if not GetFileDateTime(aFileName, CreationTime, LastAccessTime, LastWriteTime) then
    Exit;

  ftCreationTime := DateTimeToFileTime(CreationTime);
  ftLastAccessTime:= DateTimeToFileTime(aNewAccessTime);
  ftLastWriteTime:= DateTimeToFileTime(LastWriteTime);

  FileHandle:= FileOpen(aFileName, fmOpenReadWrite or fmShareExclusive);
  try
    if SetFileTime(FileHandle, @ftCreationTime, @ftLastAccessTime, @ftLastWriteTime) then
      Result:= True
  finally
    FileClose(FileHandle)
  end
end; { SetLastAccessTime }


function SetLastWriteTime(const aFileName: String; aNewModifyTime: TDateTime): Boolean;
var
  FileHandle: Cardinal;
  CreationTime, LastAccessTime, LastWriteTime: TDateTime;
  ftCreationTime, ftLastAccessTime, ftLastWriteTime: TFileTime;
begin
  Result:= False;
  if not GetFileDateTime(aFileName, CreationTime, LastAccessTime, LastWriteTime) then
    Exit;

  ftCreationTime := DateTimeToFileTime(CreationTime);
  ftLastAccessTime:= DateTimeToFileTime(LastAccessTime);
  ftLastWriteTime:= DateTimeToFileTime(aNewModifyTime);

  FileHandle:= FileOpen(aFileName, fmOpenReadWrite or fmShareExclusive);
  try
    if SetFileTime(FileHandle, @ftCreationTime, @ftLastAccessTime, @ftLastWriteTime) then
      Result:= True
  finally
    FileClose(FileHandle)
  end
end; { SetLastWriteTime }

end.

用法很简单:

// For Test: Drag two files in executable program self

program FileDateUpdate;

{$APPTYPE CONSOLE}

uses
  Windows, FileTimeUtils;

{$R *.res}

var
  FirstFile, UpdateFile, msg1, msg2: String;
  CreationTime, LastWriteTime, LastAccessTime: TDateTime;

begin
  FirstFile := ParamStr(1);
  UpdateFile:= ParamStr(2);

  msg1:= 'First file is  ' + FirstFile + '   -   Second file is  ' + UpdateFile;

  msg1:= msg1 + #13#10 + #13#10 + 'Note: The second file get the date of first file...';

  msg2:= ' Confirm ?';

  if MessageBox(0, Pchar(msg1), Pchar(msg2), MB_YESNO + MB_ICONQUESTION) = IDYES  then
  begin
    GetFileDateTime(FirstFile, CreationTime, LastAccessTime, LastWriteTime);
    SetFileDateTime(UpdateFile, CreationTime, LastAccessTime, LastWriteTime)
  end
end.
`