FileExists和修改日期的问题

Zig*_*giZ 12 delphi delphi-7

在我的服务器上有几个文件的修改日期31/DEC/1979(不要问我原因).所以FileExists返回false.

Sysutils.FileExists 看起来像这样:

function FileAge(const FileName: string): Integer;
var
  Handle: THandle;
  FindData: TWin32FindData;
  LocalFileTime: TFileTime;
begin
  Handle := FindFirstFile(PChar(FileName), FindData);
  if Handle <> INVALID_HANDLE_VALUE then
  begin
    Windows.FindClose(Handle);
    if (FindData.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY) = 0 then
    begin
      FileTimeToLocalFileTime(FindData.ftLastWriteTime, LocalFileTime);
      if FileTimeToDosDateTime(LocalFileTime, LongRec(Result).Hi,
        LongRec(Result).Lo) then Exit;
    end;
  end;
  Result := -1;
end;

function FileExists(const FileName: string): Boolean;
begin
  Result := FileAge(FileName) <> -1;
end;
Run Code Online (Sandbox Code Playgroud)

我的问题是,为什么功能首先取决于FileAge?以下行不够吗?:

if (FindData.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY) = 0 then
  // Yes the file exists!
Run Code Online (Sandbox Code Playgroud)

甚至基于文件属性:

function MyFileExists(const Name: string): Boolean;
var
  R: DWORD;
begin
  R := GetFileAttributes(PChar(Name));
  Result := (R <> DWORD(-1)) and ((R and FILE_ATTRIBUTE_DIRECTORY) = 0);
end;
Run Code Online (Sandbox Code Playgroud)

Dav*_*nan 11

Delphi的现代版本的实现FileExists方式与代码的实现方式大致相同.该实现对符号链接有额外的处理,但在其他方面基本上与您的版本相同.

现代Delphi实现中有一个有趣的细微差别.如果调用GetFileAttributes返回INVALID_FILE_ATTRIBUTES,则代码不会立即挽救.相反,它这样做:

LastError := GetLastError;
Result := (LastError <> ERROR_FILE_NOT_FOUND) and
  (LastError <> ERROR_PATH_NOT_FOUND) and
  (LastError <> ERROR_INVALID_NAME) and ExistsLockedOrShared(Filename);
Run Code Online (Sandbox Code Playgroud)

和实施ExistsLockedOrShared用途FindFirstFile和的检查 FILE_ATTRIBUTE_DIRECTORYdwFileAttributes.这表示GetFileAttributes文件存在时可能会失败,但是已锁定.但FindFirstFile在这种情况下,这可以成功.这是合理的,因为FindFirstFile使用文件元数据而不是文件本身存储的数据.

很难说为什么代码就像旧版本一样.我觉得它很弱.我个人会FileExists用更好的版本替换,使用代码钩子.例如:在delphi中调用例程调用

和往常一样,有一篇关于这个主题的Raymond Chen文章:Superstition:为什么GetFileAttributes是老式的测试文件存在的方式?

  • 是的,我认为这应该是一种常见做法.[MSDN - `最佳实践是所有应用程序在启动时使用参数SEM_FAILCRITICALERRORS调用流程范围的SetErrorMode函数.](http://msdn.microsoft.com/en-us/library/windows/desktop/ms680621( v = vs.85)的.aspx). (3认同)
  • +1像所有老前辈一样,我也在用我的D5使用`GetFileAttributes`来检查文件是否存在.但不知道锁定/共享问题.你能否发布`FileExists`的完整代码实现?:)这是我在[D2009](http://embarcadero.newsgroups.archived.at/public.delphi.language.delphi.win32/200903/0903173087.html)中找到的. (2认同)
  • @kobik我在流程开始时添加`SEM_FAILCRITICALERRORS`. (2认同)