如何在Windows中比较可能的替代文件名?

问题描述 投票:2回答:3

不幸的是,Windows中的目录/文件名不区分大小写。

当我将文本(来自用户的输入)与目录名(来自CFileFind)进行比较时,如何检查它们是否表示相同的目录?例如C:\PIPPO\C:\Pippo\是同一目录,而C:\Pippò\则不一样(最后一个有重音)。

我正在尝试:

if(CompareString(LOCALE_INVARIANT,NORM_IGNORECASE,q,-1,data_from_CfileFind->txt.GetBuffer(),-1)==CSTR_EQUAL)

q是[用户输入的一部分])

它“有点工作”,因为它识别罗马,希腊和西里尔字母的案例变体的相同目录,但它混淆"weiß""weiss"(它们是我的光盘上的两个不同的目录),所以它不可靠。

[失败的测试受到Comparing and sorting Unicode filenames的启发:我已经阅读过,但没有找到合适的解决方案 - 链接似乎不起作用)

(我也读过Windows Invariant Culture Puzzle,但我担心我对“文化”并不完全了解)。

有什么建议吗?

也许我应该用不同的参数调用CompareString()?或者有更好,更简单的方法吗?

请注意,我不需要对名称进行排序:我只想检查它们是否与Windows相同的目录(或文件)。

“Windows”,我的意思是从2000年(或至少XP)以后。

编辑(对不起,第一次问题不是很好)

1)用户输入的路径不保证引用实际存在的目录(在这种情况下,当然,它们不是同一目录)。

2)我知道文件和目录可以用非常不同的名称来引用,因为链接(硬或软),substs,具有不同名称或IP的网络访问到同一台计算机等等......但我不是问检测所有这些案件。我要检查的是,用户编写的名称是否是另一个现有名称的大小写(因此,例如,如果我尝试创建一个具有相同名称的文件,Windows会告诉我该文件已经存在但不同的情况)。

第二次编辑

这样做(至少在我尝试过的情况下):

if(CompareStringOrdinal(q,-1,data_from_CfileFind->txt.GetBuffer(),-1,1)==CSTR_EQUAL)

CompareStringOrdinal()在较旧的Windows版本中不可用。有没有相应的?

c++ windows filenames
3个回答
2
投票

最好的方法(我知道)检查两个文件系统路径是否引用相同的项目,而不采用字符串比较,是:

  1. 使用HANDLECreateFile()s打开到两个路径,然后从HANDLEs获取唯一的文件系统ID并将它们进行相等性比较。在FAT和NTFS上,使用来自dwVolumeSerialNumbernFileIndex(Low|High)GetFileInformationByHandle()的组合。在ReFS上,使用来自VolumeSerialNumberFileIdGetFileInformationByHandleEx(FileIdInfo)的组合。您可以使用GetVolumeInformation()来检测每个路径正在使用哪个文件系统。 这种方法分别在BY_HANDLE_FILE_INFORMATIONFILE_ID_INFO文档中描述: 标识符(低和高部分)和卷序列号唯一地标识单个计算机上的文件。要确定两个打开的句柄是否表示同一文件,请合并每个文件的标识符和卷序列号并进行比较。 文件的128位文件标识符。文件标识符和卷序列号唯一标识单个计算机上的文件。要确定两个打开的句柄是否表示同一文件,请合并每个文件的标识符和卷序列号并进行比较。
  2. 与文件系统无关的方法是使用SHGetDesktopFolder()获取Shell命名空间的根桌面的IShellFolder接口,然后使用桌面的IShellFolder::ParseDisplayName()方法(或使用独立的SHParseDisplayName()函数)解析两个路径到绝对PIDL,然后使用qzxswpoi比较PIDL桌面的IShellFolder::CompareIDs()方法。

1
投票

首先在每条路径上调用GetFullPathName,然后执行GetLongPathName,最后对结果进行不区分大小写的比较。

GetFullPathName将为每个文件提供完全限定的路径。然后GetLongPathName获取该路径的每个组件的真实名称,因此如果有人使用Windows 95/98样式的短名称作为文件/目录,那就不会混淆了。


0
投票

这就是它的工作方式:

1)在程序开始时,调用setlocale(LC_CTYPE, "");

2)然后将字符串与if(!data_from_CfileFind->txt.CompareNoCase(q))(调用_wcsicmp调用_wcsicmp_l)进行比较

© www.soinside.com 2019 - 2024. All rights reserved.