1

哟。

我需要扫描一个目录及其子文件夹,我使用了 FindFirst 和 FindNext 程序,但是 TSearchRec 的 Name 属性是一个字符串,因此 unicode 文件夹名称(希伯来语、阿拉伯语等)是 '?????' 在名称属性中。

我尝试使用带有 WideFindFirst、WideFindNext 和 TSearchRecW 的 TntComponent。但我还是得到了??????用于文件夹名称。

 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 回答 4

4

Delphi 通过使用 WideString 在编译器中支持 unicode。

但是你会面临以下问题:

  • Delphi < 2009 在其 VCL 中不支持 unicode。
  • 许多 API 映射是在 API 的 ANSI(例如 OpenFileA)变体上完成的。
  • delphi 编译器会大量地将 WideStrings 转换为字符串,因此对它们要非常明确。

如果您使用原始的 unicode windows api,它将起作用。

所以 FindFirst 使用了 delphi 映射到 FindFirstFileA 变体的 api FindFirstFile,你需要直接调用 FindFirstW。

因此,您将有 2 个选择。

  1. 升级到 Delphi 2009 并为您完成大量 unicode 映射
    • 编写自己的 unicode 映射函数

对于文本文件的编写,您可以使用 Primoz Gabrijelcic(又名 gabr)的GpTextFileGpTextSteam,它们支持 unicode。

她是使用 unicode 文件名打开文件的示例:

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;

I've used these functions because the ANSI api's have a path limit of 254 chars, the unicode have a limit of 2^16 chars if I'm not mistaken.

After you've got the handle to the file you can just call the regular ReadFile delphi api mapping, to read data from your file.

于 2009-01-19T10:05:03.097 回答
2

2009 年之前的 Delphi 版本对 unicode 的支持非常有限。所以如果你真的想要 unicode,那么我强烈建议你升级到 2009。在 2009 中,默认字符串是 unicode。

你说你仍然有宽版本的垃圾字符。您是否尝试过使用调试器检查这些值?2009 年之前的 delphi 的 vcl 不能显示 unicode 字符。

于 2009-01-19T08:59:48.327 回答
0

一些更新.. 如果我在 SearchRec.Name 上使用 UTF8Encode,我会得到 unicode 字符串!下一个问题是我使用的 TFileStream。我找不到它的 WideString 版本(用于文件名)。

于 2009-01-19T09:40:45.080 回答
0

您可以使用 CreateFileW 打开文件并获取句柄,然后使用 THandleStream 而不是 TFileStream 来读取文件。

Tnt Unicode(现在是 TMS Unicode)有一个 TTntFileStream 可以打开基于宽字符串的文件。正如 Gamecat 所说,如果你想做 unicode,你真的应该升级到 Delphi 2009。(一般来说很棒的版本)

于 2009-01-19T09:58:51.080 回答