FileExists returns true 但文件不存在

FileExists returns true but file doesn't exist

我在 Delphi 7 中编写我的程序。我只需要它处理非 Unicode 文件名。如果它找到一个 Unicode 文件名,它应该忽略它。

我的代码如下所示:

var Filename: String;

if not FileExists(Filename) then Exit;

F := TFileStream(Filename, fmOpenRead or fmShareDenyWrite);

然而,对于某些 Unicode 文件名,FileExists() returns true 但随后 TFileStream 引发异常,因为路径无效。

例如: 名为 "loop 輪紋.jpg" 的文件作为 "loop ??.jpg" 读入文件名。这是预期的行为。 TFileStream 无法读取此类文件(因为目录中没有 "loop ??.jpg")并引发异常。但是 FileExists() 应该发现这个文件不存在。为什么它不起作用?因为它被定义为:

function FileExists(const FileName: string): Boolean;
begin
  Result := FileAge(FileName) <> -1;
end;

并且 FileAge() 定义为:

function FileAge(const FileName: string): Integer;
var
  Handle: THandle;
  FindData: TWin32FindData;
  LocalFileTime: TFileTime;
begin
  Handle := FindFirstFile(PChar(FileName), FindData);
...

FindFirstFile 使用 "loop ??.jpg" 作为掩码,然后找到 "loop 輪紋.jpg".

所以问题是:

1) 我可以在 Delphi 7 中轻松地在 TFileStream 中使用 Unicode 文件名吗?

2) 我应该使用什么函数而不是 FileExists 来获得正确的结果?

  1. 不是 TFileStream 本身,不是。但是您可以改用 Win32 CreateFileW() to open the Unicode filename, and then assign the returned HANDLE to a THandleStream。这基本上就是 TFileStream 内部所做的(在 Delphi 7 中使用 CreateFileA())。

  2. Delphi 的更高版本在其实现中使用 Win32 GetFileAttributes() 1 而不是 RTL 的 FileAge() FileExists()GetFileAttributes() 不支持通配符,而 FindFirstFile() 支持。

    1. 参见 Why is GetFileAttributes the way old-timers test file existence?

或者,您可以在打开文件之前根本不检查文件是否存在,只是无条件地打开它并捕获由此产生的错误。 OS 会告诉您失败是由于找不到文件还是其他错误。