不幸的是,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)我知道由于链接(硬或软),subst
,对同一台计算机使用不同名称或IP的网络访问等原因,文件和目录可以用非常不同的名称来引用。 ..但我不是要检测所有这些情况。
我要检查的是用户写的名称是否是另一个现有名称的大小写变化(因此,例如,Windows会告诉我,如果我尝试创建一个具有相同名称的文件,则该文件已经存在。但情况不同。
第二次编辑
这可以完成工作(至少在我尝试过的情况下):
if(CompareStringOrdinal(q,-1,data_from_CfileFind->txt.GetBuffer(),-1,1)==CSTR_EQUAL)
但是CompareStringOrdinal()
在较旧的Windows版本中不可用。
有什么等效的吗?
答案 0 :(得分:2)
(据我所知)检查两个文件系统路径是否引用同一项目的最佳方法,不求助于字符串比较的方法是:
使用CreateFile()
打开HANDLE
到两个路径,然后从HANDLE
获得唯一的文件系统ID并比较它们是否相等。在FAT和NTFS上,使用GetFileInformationByHandle()
中dwVolumeSerialNumber
和nFileIndex(Low|High)
的组合。在ReFS上,请使用GetFileInformationByHandleEx(FileIdInfo)
中VolumeSerialNumber
和FileId
的组合。您可以使用GetVolumeInformation()
来检测每个路径正在使用哪个文件系统。
分别在BY_HANDLE_FILE_INFORMATION
和FILE_ID_INFO
文档中对此方法进行了描述:
标识符(上下两部分)和卷序列号唯一地标识一台计算机上的文件。要确定两个打开的句柄是否代表同一个文件,请将每个文件的标识符和卷序列号组合起来并进行比较。
文件的128位文件标识符。文件标识符和卷序列号唯一地标识一台计算机上的文件。要确定两个打开的句柄是否代表同一个文件,请将每个文件的标识符和卷序列号组合起来并进行比较。
与文件系统无关的方法是使用SHGetDesktopFolder()
获取Shell命名空间的根桌面的IShellFolder
接口,然后使用桌面的{{3 }}方法(或使用独立的IShellFolder::ParseDisplayName()
函数),然后使用桌面的SHParseDisplayName()
方法比较PIDL。
答案 1 :(得分:1)
首先在每个路径上调用GetFullPathName,然后进行GetLongPathName,最后对结果进行不区分大小写的比较。
import Carbon.HIToolbox.Events
@IBAction func buttonPressed(_ sender: AnyObject) {
//let keyCode = CGKeyCode(kVK_F11)
let keyCode = CGKeyCode(kVK_VolumeUp)
let keySource = CGEventSource(stateID: .hidSystemState)
let keyDownEvent = CGEvent(keyboardEventSource: keySource,
virtualKey: keyCode,
keyDown: true)
//keyDownEvent?.flags = .maskCommand
//keyDownEvent?.flags = .maskControl
//keyDownEvent?.flags = .maskAlternate
//keyDownEvent?.flags = .maskSecondaryFn
//keyDownEvent?.flags = .maskShift
//keyDownEvent?.flags = .maskNumericPad
//keyDownEvent?.flags = .maskHelp
let keyUpEvent = CGEvent(keyboardEventSource: keySource,
virtualKey: keyCode,
keyDown: false)
keyDownEvent?.post(tap: .cghidEventTap)
keyUpEvent?.post(tap: .cghidEventTap)
}
将为每个文件提供完全限定的路径。 GetFullPathName
然后获得该路径的每个组件的真实名称,因此,如果有人使用Windows 95/98样式的文件/目录简称,就不会造成混乱。
答案 2 :(得分:0)
这就是它的工作方式:
1)在程序开始时,调用setlocale(LC_CTYPE, "");
2)然后将字符串与if(!data_from_CfileFind->txt.CompareNoCase(q))
(调用_wcsicmp
并调用_wcsicmp_l
的字符串进行比较)