Сканер папок Delphi - имена папок в Юникоде - PullRequest
1 голос
/ 19 января 2009

Yo.

Мне нужно сканировать каталог и его подпапки, я использовал процедуры FindFirst и FindNext, но свойство TSearchRec's Name является строкой, поэтому имена папок в юникоде (иврит, арабский и т. Д.) Являются «?????» в свойстве Name.

Я пытался использовать TntComponent, с WideFindFirst, WideFindNext и TSearchRecW. Но я все еще получаю ?????? для имен папок.

 Flname:=WideExtractFileName(FileSpec);
 validres := WideFindFirst(FileSpec+'\*', faDirectory, SearchRec);
 AssignFile(LogFile, ResultFilePath);

 while validres=0 do begin
   if (SearchRec.Attr and faDirectory>0) and (SearchRec.Name[1]<>'.') then begin
     {invalid entry Findnext returns}
     Append(LogFile);
     WriteLn(LogFile, FileSpec+'\'+LowerCase(SearchRec.Name));
     CloseFile(LogFile);
     DirScan(FileSpec+'\'+SearchRec.Name, ResultFilePath)
   end;
   validres:=WideFindNext(SearchRec);
 end;
 WideFindClose(SearchRec);

Ответы [ 4 ]

4 голосов
/ 19 января 2009

Delphi поддерживает Unicode в компиляторе, используя WideString.

Но вы столкнетесь со следующими проблемами:

  • Delphi <2009 не поддерживает юникод в своих VCL. </li>
  • В API-вариантах ANSI (например, OpenFileA) сделано много сопоставлений API.
  • Компилятор delphi будет часто преобразовывать WideStrings в строку, поэтому будьте предельно откровенны с ними.

Это будет работать, если вы используете необработанные интерфейсы API Unicode для Windows.

Таким образом, FindFirst использует API FindFirstFile , который delphi сопоставляется с вариантом FindFirstFileA, и вам необходимо напрямую вызвать FindFirstW.

Таким образом, у вас будет 2 варианта.

  1. Обновите до Delphi 2009 и сделайте много юникодных сопоставлений для вас
    • Напишите свои собственные функции отображения Unicode

Для записи текстового файла вы можете использовать GpTextFile или GpTextSteam от Primoz Gabrijelcic (он же gabr), они имеют поддержку юникода.

Это пример открытия файла с именем файла в юникоде:

function OpenLongFileName(const ALongFileName: WideString; SharingMode: DWORD): THandle;  overload;
begin
  if CompareMem(@(WideCharToString(PWideChar(ALongFileName))[1]), @('\\'[1]), 2) then
    { Allready an UNC path }
    Result := CreateFileW(PWideChar(ALongFileName), GENERIC_READ, SharingMode, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)
  else
    Result := CreateFileW(PWideChar('\\?\' + ALongFileName), GENERIC_READ, SharingMode, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
end;

function CreateLongFileName(const ALongFileName: WideString; SharingMode: DWORD): THandle; overload;
begin
  if CompareMem(@(WideCharToString(PWideChar(ALongFileName))[1]), @('\\'[1]), 2) then
    { Allready an UNC path }
    Result := CreateFileW(PWideChar(ALongFileName), GENERIC_WRITE, SharingMode, nil, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0)
  else
    Result := CreateFileW(PWideChar('\\?\' + ALongFileName), GENERIC_WRITE, SharingMode, nil, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
end;

Я использовал эти функции, потому что для API-интерфейса ANSI ограничение пути составляет 254 символа, а для Unicode - 2 ^ 16 символов, если я не ошибаюсь.

После того, как вы получили дескриптор файла, вы можете просто вызвать обычное отображение delphi api ReadFile, чтобы прочитать данные из вашего файла.

2 голосов
/ 19 января 2009

Delphi версии до 2009 года имеют очень ограниченную поддержку юникода. Поэтому, если вы действительно хотите использовать Unicode, я настоятельно рекомендую вам обновить его до 2009 года. В 2009 году по умолчанию используется Unicode.

Вы говорите, что у вас все еще есть мусорные персонажи с широкими версиями. Вы пытались проверить значения с помощью отладчика? Vcl версии до 2009 Delphi не может отображать символы Unicode.

0 голосов
/ 19 января 2009

Вы можете использовать CreateFileW, чтобы открыть файл и получить дескриптор, а затем использовать THandleStream вместо TFileStream для чтения файла.

Tnt Unicode (теперь TMS Unicode) имеет TTntFileStream, который может открывать файлы на основе широкой строки. И, как сказал Gamecat, если вы хотите использовать Unicode, вам действительно стоит перейти на Delphi 2009. (в общем, потрясающий релиз)

0 голосов
/ 19 января 2009

Некоторое обновление. Если я использую UTF8Encode в SearchRec.Name, я получаю строку Unicode! Следующая проблема - TFileStream, который я использую. Я не смог найти для него версию WideString (для имен файлов).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...