C# 如何在Windows上获取区分大小写的路径?
我需要知道给定路径的真实路径 例如: 实际路径是:d:\src\File.txtC# 如何在Windows上获取区分大小写的路径?,c#,.net,filepath,C#,.net,Filepath,我需要知道给定路径的真实路径 例如: 实际路径是:d:\src\File.txt 用户给我:D:\src\file.txt 因此,我需要:d:\src\File.txt您可以使用此功能: [DllImport("kernel32.dll", SetLastError=true, CharSet=CharSet.Auto)] static extern uint GetLongPathName(string ShortPath, StringBuilder sb, int buffer); [D
用户给我:D:\src\file.txt
因此,我需要:d:\src\File.txt您可以使用此功能:
[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;
}
[DllImport(“kernel32.dll”,SetLastError=true,CharSet=CharSet.Auto)]
静态外部uint GetLongPathName(字符串短路径、StringBuilder sb、int缓冲区);
[DllImport(“kernel32.dll”)]
静态外部uint GetShortPathName(字符串长路径、StringBuilder sb、int缓冲区);
受保护的静态字符串GetWindowsPhysicalPath(字符串路径)
{
StringBuilder=新的StringBuilder(255);
//具有长扩展名的名称可能导致短名称实际大于
//长长的名字。
GetShortPathName(路径、生成器、生成器容量);
path=builder.ToString();
uint result=GetLongPathName(路径、生成器、builder.Capacity);
if(结果>0&&result0)
{
//缓冲区中需要更多的容量
//在结果变量中指定
生成器=新的StringBuilder((int)结果);
结果=GetLongPathName(路径、生成器、builder.Capacity);
生成器[0]=字符ToLower(生成器[0]);
返回builder.ToString(0,(int)结果);
}
返回null;
}
在Windows上,路径不区分大小写。所以这两条路都是同样真实的
如果您想获得某种具有规范大写形式的路径(即Windows认为应该如何大写),可以使用该路径作为掩码调用FindFirstFile(),然后获取找到的文件的全名。如果路径无效,则自然无法获得规范名称。获取文件实际路径的方法(这对文件夹不起作用)是按照以下步骤操作:
CreateFileMapping
为文件创建映射GetMappedFileName
获取文件名QueryDosDevice
将其转换为MS DOS样式的路径名CreateFile
或NtOpenFile
获取文件/文件夹的句柄NtQueryObject
获取完整路径名FileNameInformation
调用NtQueryInformationFile
,以获取卷的相对路径\Device\HarddiskVolume1\Hello.txt
,第二个路径为\Hello.txt
,则您现在知道卷的路径为\Device\HarddiskVolume1
QueryDosDevice
转换,将完整NT样式路径的卷部分替换为驱动器号现在您有了文件的实际路径。作为一个老前辈,我总是使用FindFirstFile来实现这一目的。Net翻译为:
Directory.GetFiles(Path.GetDirectoryName(userSuppliedName), Path.GetFileName(userSuppliedName)).FirstOrDefault();
这只会为路径的文件名部分获得正确的大小写,而不是整个路径
JeffreyLWhitledge的评论提供了一个指向递归版本的链接,该版本可以(尽管不总是)解析完整路径。由于Borja的答案不适用于禁用8.3名称的卷,这里是Tergiver建议的递归实现(适用于文件和文件夹以及UNC共享的文件和文件夹,但不适用于其计算机名或共享名) 不存在的文件或文件夹没有问题,存在的文件或文件夹已验证并更正,但您可能会遇到文件夹重定向问题,例如,当尝试获取“C:\WinDoWs\sYsteM32\driVErs\eTC\Hosts”的正确路径时,您将在64位WinDoWs上获得“C:\WinDoWs\sYsteM32\driVErs\eTC\Hosts”,因为没有带“eTC”的“eTC”文件夹“C:\Windows\sysWOW64\drivers” 测试场景:
Directory.CreateDirectory(@"C:\Temp\SomeFolder");
File.WriteAllLines(@"C:\Temp\SomeFolder\MyTextFile.txt", new String[] { "Line1", "Line2" });
用法:
FileInfo myInfo = new FileInfo(@"C:\TEMP\SOMEfolder\MyTeXtFiLe.TxT");
String myResult = myInfo.GetFullNameWithCorrectCase(); //Returns "C:\Temp\SomeFolder\MyTextFile.txt"
代码:
这里有一个替代解决方案,适用于文件和目录。使用GetFinalPathNameByHandle,根据文档,它仅支持Vista/Server2008或更高版本的桌面应用程序 请注意,如果您给它一个符号链接,它将解析该符号链接,这是查找“最终”路径的一部分
替代解决方案 下面是一个解决方案,它使用区分大小写的路径在Windows和服务器之间移动文件。它沿着目录树走,并使用
GetFileSystemEntries()
更正每个条目。如果部分路径无效(UNC或文件夹名),然后它只更正路径直到该点,然后使用原始路径处理它找不到的内容。无论如何,希望这将在处理相同问题时节省其他人的时间
private string GetCaseSensitivePath(string path)
{
var root = Path.GetPathRoot(path);
try
{
foreach (var name in path.Substring(root.Length).Split(Path.DirectorySeparatorChar))
root = Directory.GetFileSystemEntries(root, name).First();
}
catch (Exception e)
{
// Log("Path not found: " + path);
root += path.Substring(root.Length);
}
return root;
}
我试图避免dll导入,所以对我来说最好的方法是使用System.Linq和System.IO.Directory类 以你为例 实际路径为:d:\src\File.txt 用户给了我:D:\src\file.txt 代码: 使用System.Linq
public static class PathUtils
{
public static string RealPath(string inputPath)
{
return Directory.GetFiles(Path.GetDirectoryName(inputPath))
.FirstOrDefault(p => String.Equals(Path.GetFileName(p),
Path.GetFileName(inputPath), StringComparison.OrdinalIgnoreCase));
}
}
var p=PathUtils.RealPath(@“D:\src\file.txt”)
方法应该返回路径“d:\src\File.txt”或“d:\src\File.txt”。我的印象是Windows有一个基本上不区分大小写的文件系统。在这种情况下,这充其量是不必要的,最坏的情况是……胡说八道。)@djacobson:你错了。Windows基本上是区分大小写的,但某些标志使它的行为不区分大小写。有关详细信息,请搜索
OBJ_case_INSENSITIVE
。例如,如果你正在编写BASH emulator,那么你自然需要文件的正确大小写。我需要应用
private string GetCaseSensitivePath(string path)
{
var root = Path.GetPathRoot(path);
try
{
foreach (var name in path.Substring(root.Length).Split(Path.DirectorySeparatorChar))
root = Directory.GetFileSystemEntries(root, name).First();
}
catch (Exception e)
{
// Log("Path not found: " + path);
root += path.Substring(root.Length);
}
return root;
}
public static class PathUtils
{
public static string RealPath(string inputPath)
{
return Directory.GetFiles(Path.GetDirectoryName(inputPath))
.FirstOrDefault(p => String.Equals(Path.GetFileName(p),
Path.GetFileName(inputPath), StringComparison.OrdinalIgnoreCase));
}
}