Delphi文件夹扫描程序 - Unicode文件夹名称

时间:2022-01-24 20:23:45

Yo.

I need to scan a directory and its sub-folders, I used FindFirst and FindNext procedures, but the TSearchRec's Name property is a string, thus unicode folder names (hebrew, arabic etc) are '?????' in the Name property.

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

I tried using TntComponent, with WideFindFirst, WideFindNext and TSearchRecW. But I still get ?????? for folder names.

我尝试使用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 个解决方案

#1


Delphi versions prior to 2009 have very limited unicode support. So if you really want unicode, then I strongly advise you to upgrade to 2009. In 2009 the default string is unicode.

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

You say that you still got garbage characters with the wide versions. Have you tried to inspect the values with the debugger? The vcl of pre 2009 delphi can not show unicode chars.

你说你仍然有宽版本的垃圾字符。您是否尝试使用调试器检查值? 2009年德尔福之前的vcl无法显示unicode字符。

#2


Delphi does support unicode in the compiler by using WideString.

Delphi使用WideString支持编译器中的unicode。

But you'll face the following problems:

但是你会遇到以下问题:

  • Delphi < 2009 does not support unicode in their VCL.
  • Delphi <2009在他们的VCL中不支持unicode。

  • A lot of API mapping is done on the ANSI (OpenFileA for instance) variants of the API.
  • 很多API映射都是在API的ANSI(OpenFileA)变体上完成的。

  • The delphi compiler will convert the WideStrings to a string a lot, so be very explicit about them.
  • delphi编译器会将WideStrings转换为很多字符串,所以要非常明确。

It will work if you use the raw unicode windows api's.

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

So FindFirst uses the api FindFirstFile which delphi maps to the FindFirstFileA variant, and you'll need to directly call FindFirstW.

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

So you'll have 2 options.

所以你有2个选择。

  1. Upgrade to Delphi 2009 and have a lot of unicode mapping done for you
    • Write your own unicode mapping functions
    • 编写自己的unicode映射函数

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

For the text file writing you might be able to use the GpTextFile or GpTextSteam by Primoz Gabrijelcic (aka gabr), they have unicode support.

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

Her is an example of opening a file with a unicode filename:

她是打开带有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.

我已经使用了这些函数,因为ANSI api的路径限制为254个字符,如果我没有弄错,unicode的限制为2 ^ 16个字符。

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.

获得文件句柄后,您可以调用常规的ReadFile delphi api映射,从文件中读取数据。

#3


Some update.. If I use UTF8Encode on the SearchRec.Name I get the unicode string! Next problem is TFileStream I use. I couldn't find a WideString version for it(for filenames).

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

#4


You could use CreateFileW to open the file and get a handle then use THandleStream instead of TFileStream to read the file.

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

Tnt Unicode (TMS Unicode now) has a TTntFileStream which can open files based on widestring. And as Gamecat stated, if you want to do unicode you should really upgrade to Delphi 2009. (awesome release in general)

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

#1


Delphi versions prior to 2009 have very limited unicode support. So if you really want unicode, then I strongly advise you to upgrade to 2009. In 2009 the default string is unicode.

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

You say that you still got garbage characters with the wide versions. Have you tried to inspect the values with the debugger? The vcl of pre 2009 delphi can not show unicode chars.

你说你仍然有宽版本的垃圾字符。您是否尝试使用调试器检查值? 2009年德尔福之前的vcl无法显示unicode字符。

#2


Delphi does support unicode in the compiler by using WideString.

Delphi使用WideString支持编译器中的unicode。

But you'll face the following problems:

但是你会遇到以下问题:

  • Delphi < 2009 does not support unicode in their VCL.
  • Delphi <2009在他们的VCL中不支持unicode。

  • A lot of API mapping is done on the ANSI (OpenFileA for instance) variants of the API.
  • 很多API映射都是在API的ANSI(OpenFileA)变体上完成的。

  • The delphi compiler will convert the WideStrings to a string a lot, so be very explicit about them.
  • delphi编译器会将WideStrings转换为很多字符串,所以要非常明确。

It will work if you use the raw unicode windows api's.

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

So FindFirst uses the api FindFirstFile which delphi maps to the FindFirstFileA variant, and you'll need to directly call FindFirstW.

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

So you'll have 2 options.

所以你有2个选择。

  1. Upgrade to Delphi 2009 and have a lot of unicode mapping done for you
    • Write your own unicode mapping functions
    • 编写自己的unicode映射函数

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

For the text file writing you might be able to use the GpTextFile or GpTextSteam by Primoz Gabrijelcic (aka gabr), they have unicode support.

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

Her is an example of opening a file with a unicode filename:

她是打开带有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.

我已经使用了这些函数,因为ANSI api的路径限制为254个字符,如果我没有弄错,unicode的限制为2 ^ 16个字符。

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.

获得文件句柄后,您可以调用常规的ReadFile delphi api映射,从文件中读取数据。

#3


Some update.. If I use UTF8Encode on the SearchRec.Name I get the unicode string! Next problem is TFileStream I use. I couldn't find a WideString version for it(for filenames).

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

#4


You could use CreateFileW to open the file and get a handle then use THandleStream instead of TFileStream to read the file.

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

Tnt Unicode (TMS Unicode now) has a TTntFileStream which can open files based on widestring. And as Gamecat stated, if you want to do unicode you should really upgrade to Delphi 2009. (awesome release in general)

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