Eam*_*nne 70 .net c# filesystems path
如果我有两个DirectoryInfo对象,我如何比较它们的语义相等?例如,以下路径应全部视为等于C:\temp:
C:\tempC:\temp\C:\temp\.C:\temp\x\..\..\temp\.以下可能等于或不等于C:\temp:
\temp 如果当前工作目录在驱动器上 C:\temp 如果当前工作目录是 C:\C:\temp.C:\temp...\如果考虑当前的工作目录很重要,我可以自己解决这个问题,所以这并不重要.尾随点在窗口中被剥离,因此这些路径确实应该相等 - 但它们不会在unix中被剥离,所以在mono下我会期望其他结果.
区分大小写是可选的.路径可能存在也可能不存在,用户可能拥有或可能没有路径权限 - 我更喜欢快速健壮的方法,不需要任何I/O(所以没有权限检查),但是如果有什么内置的话 - 我对任何"足够好"的东西都很满意......
Vla*_*adV 92
GetFullPath似乎做了工作,除了case difference(Path.GetFullPath("test") != Path.GetFullPath("TEST"))和尾部斜杠.因此,以下代码应该可以正常工作:
String.Compare(
Path.GetFullPath(path1).TrimEnd('\\'),
Path.GetFullPath(path2).TrimEnd('\\'),
StringComparison.InvariantCultureIgnoreCase)
Run Code Online (Sandbox Code Playgroud)
或者,如果你想开始DirectoryInfo:
String.Compare(
dirinfo1.FullName.TrimEnd('\\'),
dirinfo2.FullName.TrimEnd('\\'),
StringComparison.InvariantCultureIgnoreCase)
Run Code Online (Sandbox Code Playgroud)
naw*_*fal 34
从这个答案,这个方法可以处理一些边缘情况:
public static string NormalizePath(string path)
{
return Path.GetFullPath(new Uri(path).LocalPath)
.TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar)
.ToUpperInvariant();
}
Run Code Online (Sandbox Code Playgroud)
原始答案中的更多细节.称之为:
bool pathsEqual = NormalizePath(path1) == NormalizePath(path2);
Run Code Online (Sandbox Code Playgroud)
应该适用于文件和目录路径.
Ste*_*ven 11
在.NET中实现路径有一些简短的方法.有很多关于它的抱怨.NDepend的创建者Patrick Smacchia发布了一个开源库,可以处理常见和复杂的路径操作.如果在应用程序的路径上执行大量比较操作,则此库可能对您有用.
我意识到这是一个老帖子,但所有答案最终都是基于两个名字的文本比较.试图获得两个"规范化"名称,几乎不可能考虑到引用相同文件对象的无数可能方式.存在诸如:交汇点,符号链接,网络文件共享(以不同方式引用相同文件对象)等等的问题. 事实上,除了Igor Korkhov之外,上面的每个答案绝对会给出不正确的结果.某些情况(例如路口,符号链接,目录链接等)
这个问题特别要求解决方案不需要任何I/O,但是如果你要处理网络路径,你绝对需要做IO:有些情况下根本无法从任何本地路径字符串确定操作,两个文件引用是否会引用相同的物理文件.(这可以很容易理解如下.假设文件服务器在共享子树中的某个地方有一个Windows目录连接.在这种情况下,可以直接或通过连接引用文件.但是联结位于文件服务器上,因此,客户端根本无法通过本地信息确定两个引用文件名是指同一个物理文件:客户端本地无法获得信息.因此必须绝对做一些最小的IO - 例如,打开两个文件对象句柄 - 确定引用是否引用相同的物理文件.)
以下解决方案执行一些IO,尽管非常小,但正确地确定两个文件系统引用是否在语义上相同,即引用相同的文件对象.(如果两个文件规范都没有引用有效的文件对象,则所有投注均关闭):
public static bool AreFileSystemObjectsEqual(string dirName1, string dirName2)
{
//Optimization: if strings are equal, don't bother with the IO
bool bRet = string.Equals(dirName1, dirName2, StringComparison.OrdinalIgnoreCase);
if (!bRet)
{
//NOTE: we cannot lift the call to GetFileHandle out of this routine, because we _must_
// have both file handles open simultaneously in order for the objectFileInfo comparison
// to be guaranteed as valid.
using (SafeFileHandle directoryHandle1 = GetFileHandle(dirName1), directoryHandle2 = GetFileHandle(dirName2))
{
BY_HANDLE_FILE_INFORMATION? objectFileInfo1 = GetFileInfo(directoryHandle1);
BY_HANDLE_FILE_INFORMATION? objectFileInfo2 = GetFileInfo(directoryHandle2);
bRet = objectFileInfo1 != null
&& objectFileInfo2 != null
&& (objectFileInfo1.Value.FileIndexHigh == objectFileInfo2.Value.FileIndexHigh)
&& (objectFileInfo1.Value.FileIndexLow == objectFileInfo2.Value.FileIndexLow)
&& (objectFileInfo1.Value.VolumeSerialNumber == objectFileInfo2.Value.VolumeSerialNumber);
}
}
return bRet;
}
Run Code Online (Sandbox Code Playgroud)
这个想法来自Warren Stevens在我在SuperUser上发布的类似问题的回复:https://superuser.com/a/881966/241981
似乎 P/Invoking GetFinalPathNameByHandle()将是最可靠的解决方案。
UPD:哎呀,我没有考虑到你不想使用任何 I/O