【发布时间】:2009-01-04 05:18:35
【问题描述】:
有谁知道 Win32 在处理不区分大小写的文件名时使用什么文化设置?
这是根据用户的文化而变化的,还是 Win32 使用文化不变的大小写规则?
【问题讨论】:
有谁知道 Win32 在处理不区分大小写的文件名时使用什么文化设置?
这是根据用户的文化而变化的,还是 Win32 使用文化不变的大小写规则?
【问题讨论】:
大概的答案是 Comparing Unicode file names the right way.
基本上,建议将两个字符串都大写(使用CharUpper、CharUpperBuff 或LCMapString),然后使用二进制比较(即memcmp 或wmemcmp,而不是具有不变语言环境的CompareString)进行比较。文件系统不做 Unicode 规范化,大小写规则不依赖于区域设置。
不幸的是,在处理大小写规则在不同版本的 Unicode 中发生变化的字符时,会出现模棱两可的情况,但您可以做到这一点。
【讨论】:
Comparing file names in native code 和 Don't compare filenames 是关于这个主题的几篇很好的博客文章。第一个包含用于 OrdinalIgnoreCaseCompareStrings 的 C/C++ 代码,第二个告诉您这并不总是适用于文件名以及如何缓解这种情况。
然后是 Unicode 问题。虽然这些新的
OrdinalIgnoreCase字符串比较算法非常适合您的本地 NTFS 驱动器,但它们可能无法在您的 FAT 驱动器或网络共享上产生正确的答案。那么答案是什么?如果可能,让文件系统告诉您。
CreateFile可以告诉您给定的文件名是否存在。只需选择正确的创作倾向。如果需要对比句柄,可以经常使用GetFileInformationByHandle;看看dwVolumeSerialNumber/nFileIndexHigh/nFileIndexLow。
【讨论】:
如果您使用的是 .NET,微软官方建议使用StringComparison.OrdinalIgnoreCase 进行比较,使用ToUpperInvariant 进行规范化(稍后将使用Ordinal 进行比较)。这也适用于注册表项和值、环境变量等。
更多详情请见New Recommendations for Using Strings in Microsoft .NET 2.0。
请注意,虽然它在 NTFS 上是可靠的,但它可能会因网络共享而失败,例如。请参阅@SteveSteiner 的答案和他的帖子中的链接以获取解决方案。
【讨论】:
根据Windows Driver SamplesFastFAT 和CDFS,它使用RtlUpcaseUnicodeString 将字符串转换为大写。根据对 Ghidra 的简要介绍,它使用名为 NLS_UPCASE 的内部函数,其行为基于您当前的系统代码页。
【讨论】: