FileExists возвращает true, но файл не существует - PullRequest
3 голосов
/ 29 марта 2019

Я пишу свою программу на Delphi 7. Мне нужно, чтобы она работала только с именами, отличными от Unicode. Если он находит имя файла Unicode, он должен просто игнорировать его.

Мой код выглядит так:

var Filename: String;

if not FileExists(Filename) then Exit;

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

Однако в случае некоторых имен файлов Unicode FileExists () возвращает 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 как-то легко использовать имена файлов Unicode в TFileStream?

или

2) Какую функцию я должен использовать вместо FileExists для получения правильных результатов?

1 Ответ

11 голосов
/ 29 марта 2019
  1. Не с TFileStream, нет. Но вместо этого вы можете использовать Win32 CreateFileW(), чтобы открыть имя файла Unicode, а затем присвоить возвращаемое HANDLE THandleStream. По сути, это то, что TFileStream делает внутри (используя вместо этого CreateFileA() в Delphi 7).

  2. Более поздние версии Delphi используют Win32 GetFileAttributes() 1 вместо RTL FileAge() в их реализации FileExists(). GetFileAttributes() не поддерживает подстановочные знаки, как FindFirstFile().

    1. См. Почему GetFile присваивает способ существования файла проверки старожилов?

Или вы можете вообще не проверять существование файла перед открытием файла, просто открыть его безоговорочно и отловить полученную ошибку. ОС сообщит вам, произошел ли сбой из-за того, что файл не найден, по сравнению с другой ошибкой.

...