有没有办法区分大小写Directory.Exists
/File.Exists
因为
Directory.Exists(folderPath)
和
Directory.Exists(folderPath.ToLower())
两者都返回true
?
大多数时候没关系,但我使用的是一个宏,如果路径不匹配案例 100%,它似乎不起作用。
有没有办法区分大小写Directory.Exists
/File.Exists
因为
Directory.Exists(folderPath)
和
Directory.Exists(folderPath.ToLower())
两者都返回true
?
大多数时候没关系,但我使用的是一个宏,如果路径不匹配案例 100%,它似乎不起作用。
由于 Directory.Exists 使用不区分大小写的FindFirstFile ,所以不。但是您可以使用设置为FIND_FIRST_EX_CASE_SENSITIVE的附加标志参数PInvoke FindFirstFileEx
试试这个功能:
public static bool FileExistsCaseSensitive(string filename)
{
string name = Path.GetDirectoryName(filename);
return name != null
&& Array.Exists(Directory.GetFiles(name), s => s == Path.GetFullPath(filename));
}
更新:
如评论中所述,这仅检查文件名中的案例,而不是路径中的案例。这是因为 GetFullPath 方法返回的不是带有原始 case 的 Windows 原始路径,而是来自参数的路径的副本。
前任:
GetFullPath("c:\TEST\file.txt") -> "c:\TEST\file.txt"
GetFullPath("c:\test\file.txt") -> "c:\test\file.txt"
我尝试过的所有方法都以相同的方式工作:Fileinfo、DirectoryInfo。
这是使用 kernel32.dll 方法的解决方案:
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public static extern int GetLongPathName(
string path,
StringBuilder longPath,
int longPathLength
);
/// <summary>
/// Return true if file exists. Non case sensitive by default.
/// </summary>
/// <param name="filename"></param>
/// <param name="caseSensitive"></param>
/// <returns></returns>
public static bool FileExists(string filename, bool caseSensitive = false)
{
if (!File.Exists(filename))
{
return false;
}
if (!caseSensitive)
{
return true;
}
//check case
StringBuilder longPath = new StringBuilder(255);
GetLongPathName(Path.GetFullPath(filename), longPath, longPath.Capacity);
string realPath = Path.GetDirectoryName(longPath.ToString());
return Array.Exists(Directory.GetFiles(realPath), s => s == filename);
}
基于this question的解决方案,我编写了以下代码,该代码对除Windows驱动器号之外的整个路径区分大小写:
static void Main(string[] args)
{
string file1 = @"D:\tESt\Test.txt";
string file2 = @"d:\Test\test.txt";
string file3 = @"d:\test\notexists.txt";
bool exists1 = Case_Sensitive_File_Exists(file1);
bool exists2 = Case_Sensitive_File_Exists(file2);
bool exists3 = Case_Sensitive_File_Exists(file3);
Console.WriteLine("\n\nPress any key...");
Console.ReadKey();
}
static bool Case_Sensitive_File_Exists(string filepath)
{
string physicalPath = GetWindowsPhysicalPath(filepath);
if (physicalPath == null) return false;
if (filepath != physicalPath) return false;
else return true;
}
GetWindowsPhysicalPath(string path)
我从问题中复制了代码
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
static extern uint GetLongPathName(string ShortPath, StringBuilder sb, int buffer);
[DllImport("kernel32.dll")]
static extern uint GetShortPathName(string longpath, StringBuilder sb, int buffer);
protected static string GetWindowsPhysicalPath(string path)
{
StringBuilder builder = new StringBuilder(255);
// names with long extension can cause the short name to be actually larger than
// the long name.
GetShortPathName(path, builder, builder.Capacity);
path = builder.ToString();
uint result = GetLongPathName(path, builder, builder.Capacity);
if (result > 0 && result < builder.Capacity)
{
//Success retrieved long file name
builder[0] = char.ToLower(builder[0]);
return builder.ToString(0, (int)result);
}
if (result > 0)
{
//Need more capacity in the buffer
//specified in the result variable
builder = new StringBuilder((int)result);
result = GetLongPathName(path, builder, builder.Capacity);
builder[0] = char.ToLower(builder[0]);
return builder.ToString(0, (int)result);
}
return null;
}
请注意,我发现此功能的唯一问题是,驱动器号似乎总是小写。示例:Windows 上的物理路径为:D:\Test\test.txt
,GetWindowsPhysicalPath(string path)
函数返回d:\Test\test.txt
这是检查目录是否实际存在的一种相对简单的方法。我需要这个,因为我有一个重命名文件夹的选项,它会首先检查是否不会发生冲突。因此,例如,如果我想将文件夹“cars”重命名为“Cars”。
这真的很简单。如果系统报告该文件夹存在,那么我只需在父文件夹上调用 GetDirectories,并将目录名称作为通配符传递(因此正好返回 1 个结果)。一个简单的比较给了我答案。
static public bool DirExistsMatchCase(string path)
{
// If it definitely doesn't return false
if (!Directory.Exists(path)) return false;
// Figure out if the case (of the final part) is the same
string thisDir = Path.GetFileName(path);
string actualDir = Path.GetFileName(Directory.GetDirectories(Path.GetDirectoryName(path), thisDir)[0]);
return thisDir == actualDir;
}
试试这两个不需要使用 PInvoke 并返回可为空的布尔值(bool?)的更简单的选项。我不是学科专家,所以我知道这是否是最有效的代码,但它对我有用。
只需传入一个路径,如果结果为 null (HasValue = false) 则找不到匹配项,如果结果为 false 则完全匹配,否则如果为 true 则匹配不同大小写。
GetFiles、GetDirectories 和 GetDrives 方法都返回保存在文件系统中的确切大小写,因此您可以使用区分大小写的比较方法。
注意:对于路径是精确驱动器的情况(例如@"C:\"),我必须使用稍微不同的方法。
using System.IO;
class MyFolderFileHelper {
public static bool? FileExistsWithDifferentCase(string fileName)
{
bool? result = null;
if (File.Exists(fileName))
{
result = false;
string directory = Path.GetDirectoryName(fileName);
string fileTitle = Path.GetFileName(fileName);
string[] files = Directory.GetFiles(directory, fileTitle);
if (String.Compare(files[0], fileName, false) != 0)
result = true;
}
return result;
}
public static bool? DirectoryExistsWithDifferentCase(string directoryName)
{
bool? result = null;
if (Directory.Exists(directoryName))
{
result = false;
directoryName = directoryName.TrimEnd(Path.DirectorySeparatorChar);
int lastPathSeparatorIndex = directoryName.LastIndexOf(Path.DirectorySeparatorChar);
if (lastPathSeparatorIndex >= 0)
{
string baseDirectory = directoryName.Substring(lastPathSeparatorIndex + 1);
string parentDirectory = directoryName.Substring(0, lastPathSeparatorIndex);
string[] directories = Directory.GetDirectories(parentDirectory, baseDirectory);
if (String.Compare(directories[0], directoryName, false) != 0)
result = true;
}
else
{
//if directory is a drive
directoryName += Path.DirectorySeparatorChar.ToString();
DriveInfo[] drives = DriveInfo.GetDrives();
foreach(DriveInfo driveInfo in drives)
{
if (String.Compare(driveInfo.Name, directoryName, true) == 0)
{
if (String.Compare(driveInfo.Name, directoryName, false) != 0)
result = true;
break;
}
}
}
}
return result;
}
}
如果文件的(相对或绝对)路径是:
string AssetPath = "...";
以下确保文件既存在又具有正确的大小写:
if(File.Exists(AssetPath) && Path.GetFullPath(AssetPath) == Directory.GetFiles(Path.GetDirectoryName(Path.GetFullPath(AssetPath)), Path.GetFileName(Path.GetFullPath(AssetPath))).Single())
{
}
享受!