问题 如何检查2个DirectoryInfo对象是否指向同一目录?


我有2个 DirectoryInfo 对象,并想检查它们是否指向同一目录。除了比较他们的全名,还有其他更好的方法吗?请忽略链接的情况。

这就是我所拥有的。

DirectoryInfo di1 = new DirectoryInfo(@"c:\temp");
DirectoryInfo di2 = new DirectoryInfo(@"C:\TEMP");

if (di1.FullName.ToUpperInvariant() == di2.FullName.ToUpperInvariant())
{ // they are the same
   ...   
}

谢谢。


8590
2017-11-25 01:00


起源

以下所有答案在某些情况下会给出不正确的结果,即 他们都错了。看到 stackoverflow.com/a/39399232/1082063 为了正确答案。 - David I. McIntosh


答案:


在Linux下,您可以比较它们相同的两个文件的INode编号。但在Windows下,没有这样的概念,至少我不知道。您需要使用p / invoke来解析链接(如果有的话)。

比较字符串是您可以做的最好的。请注意,使用String.Compare(str1,str2,StringComparison.InvariantCultureIgnoreCase)比您的方法快一点。


6
2017-11-25 01:39



我的回答有问题吗? - codymanix
这回答有什么问题?它为什么被标记下来?我发现使用String.Compare()的提示很好。 - tranmq
这与问题中提供的解决方案基本相同。更好的方法是使用Uri,它将处理不同的格式等。 - Matthew Cole
“但在Windows下没有这样的概念”:这是错误的,因此这个答案本质上是错误的。虽然NFS中的INode更可靠(实际上是有保证的),但可以强制窗口为您提供类似的信息。在相关文章中查看此答案: stackoverflow.com/a/39399232/1082063。 - David I. McIntosh
如果您要确定两个目录信息对象是否引用同一目录,这将无法解决问题。应该指出的是,考虑到联结,链接,网络共享等的可能性,确定两个路径名是否引用相同的文件系统对象是非常困难的。 - David I. McIntosh


您可以改用Uri对象。但是,您的Uri对象必须指向这些目录中的“文件”。该文件实际上不必存在。

    private void CompareStrings()
    {
        string path1 = @"c:\test\rootpath";
        string path2 = @"C:\TEST\..\TEST\ROOTPATH";
        string path3 = @"C:\TeSt\RoOtPaTh\";

        string file1 = Path.Combine(path1, "log.txt");
        string file2 = Path.Combine(path2, "log.txt");
        string file3 = Path.Combine(path3, "log.txt");

        Uri u1 = new Uri(file1);
        Uri u2 = new Uri(file2);
        Uri u3 = new Uri(file3);

        Trace.WriteLine(string.Format("u1 == u2 ? {0}", u1 == u2));
        Trace.WriteLine(string.Format("u2 == u3 ? {0}", u2 == u3));

    }

这将打印出来:

u1 == u2 ? True
u2 == u3 ? True

6
2018-02-11 21:52



这实际上应该是答案,因为它涵盖了像“\ .. \”这样的边缘情况并且更加强大,尽管它需要一些解决方法 - Florian K
但有一个问题,它将%51之类的东西翻译成字母而不是留下它们,所以如果你尝试这条路径: @"c:\test\rootQpath" @"C:\TEST\..\TEST\ROOT%51PATH" 它会返回true - Florian K
而 C:\  会工作,这将抛出一个 UriFormatException 如果路径是形式的 C: (省略 \ )as Path.Combine 会产生这样的事情 C:log.txt - Petaflop


灵感来自 这里

static public bool SameDirectory(string path1, string path2)
{
    return (
        0 == String.Compare(
            System.IO.Path.GetFullPath(path1).TrimEnd('\\'),
            System.IO.Path.GetFullPath(path2).TrimEnd('\\'),
            StringComparison.InvariantCultureIgnoreCase))
        ;
}    

也适用于文件......

(BTW理论上问题是重复的,但这是原始的,另一个是答案最多的......)

HTH


2
2017-07-25 10:54





不区分大小写的比较是您可以获得的最佳结果。将它解压缩到一个帮助类,以防万一人类提出了更好的方法。

public static class DirectoryInfoExtensions
{
    public static bool IsEqualTo(this DirectoryInfo left, DirectoryInfo right)
    {
        return left.FullName.ToUpperInvariant() == right.FullName.ToUpperInvariant();
    }
}

并使用:

if (di1.IsEqualTo(di2))
{
    // Code here
}

0
2017-11-25 02:58





我为最近的项目编写的一些扩展方法包括一个可以执行此操作的扩展方法:

    public static bool IsSame(this DirectoryInfo that, DirectoryInfo other)
    {
        // zip extension wouldn't work here because it truncates the longer 
        // enumerable, resulting in false positive

        var e1 = that.EnumeratePathDirectories().GetEnumerator();
        var e2 = other.EnumeratePathDirectories().GetEnumerator();

        while (true)
        {
            var m1 = e1.MoveNext();
            var m2 = e2.MoveNext();
            if (m1 != m2) return false; // not same length
            if (!m1) return true; // finished enumerating with no differences found

            if (!e1.Current.Name.Trim().Equals(e2.Current.Name.Trim(), StringComparison.InvariantCultureIgnoreCase))
                return false; // current folder in paths differ
        }
    }

    public static IEnumerable<DirectoryInfo> EnumeratePathDirectories(this DirectoryInfo di)
    {
        var stack = new Stack<DirectoryInfo>();

        DirectoryInfo current = di;

        while (current != null)
        {
            stack.Push(current);
            current = current.Parent;
        }

        return stack;
    }

    // irrelevant for this question, but still useful:

    public static bool IsSame(this FileInfo that, FileInfo other)
    {
        return that.Name.Trim().Equals(other.Name.Trim(), StringComparison.InvariantCultureIgnoreCase) &&
               that.Directory.IsSame(other.Directory);
    }

    public static IEnumerable<DirectoryInfo> EnumeratePathDirectories(this FileInfo fi)
    {
        return fi.Directory.EnumeratePathDirectories();
    }

    public static bool StartsWith(this FileInfo fi, DirectoryInfo directory)
    {
        return fi.Directory.StartsWith(directory);
    }

    public static bool StartsWith(this DirectoryInfo di, DirectoryInfo directory)
    {
        return di.EnumeratePathDirectories().Any(d => d.IsSame(directory));
    }

0
2018-04-23 15:13