在我的服务器上有一些文件与修改日期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;
我的问题是,为什么这个功能首先依赖于FileAge?
以下行不足够吗?
- if (FindData.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY) = 0 then
- // Yes the file exists!
- 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;
解决方法
Delphi的现代版本与您的代码完全相同,实现了FileExists.该实现对符号链接具有额外的处理,但与其版本基本相同.
现代德尔福实现有一个有趣的细微差别.如果对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);
ExistsLockedOrShared的实现使用FindFirstFile和对dwFileAttributes的FILE_ATTRIBUTE_DIRECTORY的检查.这表示GetFileAttributes在文件存在但被锁定时可能会失败.但是FindFirstFile可以在这种情况下成功.这是合理的,因为FindFirstFile使用文件元数据而不是文件中存储的数据.
很难说为什么代码是旧版本的方式.我觉得它很弱.我个人使用代码钩替换FileExists更好的版本.例如:Patch routine call in delphi
一如以往,有一篇关于这个问题的Raymond Chen文章:Superstition: Why is GetFileAttributes the way old-timers test file existence?