it-swarm.com.de

Wie kann ich Verzeichnispfade in C # vergleichen?

Wenn ich zwei DirectoryInfo-Objekte habe, wie kann ich sie auf semantische Gleichheit vergleichen? Zum Beispiel sollten die folgenden Pfade gleich C:\temp sein:

  • C:\temp
  • C:\temp\
  • C:\temp\.
  • C:\temp\x\..\..\temp\.

Folgendes kann C:\temp entsprechen oder nicht:

  • \temp wenn sich das aktuelle Arbeitsverzeichnis auf Laufwerk C:\ befindet
  • temp wenn das aktuelle Arbeitsverzeichnis C:\ ist
  • C:\temp.
  • C:\temp...\

Wenn es wichtig ist, das aktuelle Arbeitsverzeichnis zu berücksichtigen, kann ich das selbst herausfinden, also ist das nicht so wichtig. Nachlaufende Punkte werden in Windows gestrippt, also sollten diese Pfade eigentlich gleich sein - aber sie werden nicht in Unix gestrippt. Unter Mono würde ich andere Ergebnisse erwarten.

Die Empfindlichkeit der Schreibweise ist optional. Die Pfade können vorhanden sein oder nicht, und der Benutzer hat möglicherweise Berechtigungen für den Pfad. Ich würde eine schnelle, robuste Methode bevorzugen, für die keine E/A erforderlich ist (also keine Berechtigungsprüfung) -in würde ich mit etwas "gut genug" auch zufrieden sein ...

68
Eamon Nerbonne

Von dieser Antwort kann diese Methode einige Edge-Fälle behandeln:

public static string NormalizePath(string path)
{
    return Path.GetFullPath(new Uri(path).LocalPath)
               .TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar)
               .ToUpperInvariant();
}

Weitere Details in der ursprünglichen Antwort. Nenne es wie: 

bool pathsEqual = NormalizePath(path1) == NormalizePath(path2);

Sollte für Datei- und Verzeichnispfade funktionieren.

28
nawfal

GetFullPath scheint die Arbeit zu erledigen, abgesehen von der Falldifferenz (Path.GetFullPath("test") != Path.GetFullPath("TEST")) und dem nachgestellten Schrägstrich.

String.Compare(
    Path.GetFullPath(path1).TrimEnd('\\'),
    Path.GetFullPath(path2).TrimEnd('\\'), 
    StringComparison.InvariantCultureIgnoreCase)

Oder wenn Sie mit DirectoryInfo beginnen wollen:

String.Compare(
    dirinfo1.FullName.TrimEnd('\\'),
    dirinfo2.FullName.TrimEnd('\\'), 
    StringComparison.InvariantCultureIgnoreCase)
90
VladV

Es gibt einige Abkürzungen bei der Implementierung von Pfaden in .NET. Es gibt viele Klagen darüber. Patrick Smacchia , der Schöpfer von NDepend, veröffentlichte eine Open-Source-Bibliothek, die die Handhabung allgemeiner und komplexer Pfadoperationen ermöglicht . Wenn Sie viele Pfade in Ihrer Anwendung vergleichen, kann diese Bibliothek für Sie nützlich sein.

11
Steven
 System.IO.Path.GetFullPath(pathA).Equals(System.IO.Path.GetFullPath(PathB));
3
Asad Butt

Es scheint, dass P/Invoking GetFinalPathNameByHandle () die zuverlässigste Lösung wäre. 

UPD: Hoppla, ich habe Ihren Wunsch, keine I/O zu verwenden, nicht berücksichtigt

3
Igor Korkhov

Microsoft hat ähnliche Methoden implementiert, die jedoch nicht so nützlich sind wie die obigen Antworten:

2
Chris Xue

Sie können Minimatch verwenden, einen Port der Minimatch von Node.js.

var mm = new Minimatcher(searchPattern, new Options { AllowWindowsPaths = true });

if (mm.IsMatch(somePath))
{
    // The path matches!  Do some cool stuff!
}

var matchingPaths = mm.Filter(allPaths);


Sehen Sie, warum die Option AllowWindowsPaths = true notwendig ist:

Auf Windows-Pfaden Die Syntax von Minimatch wurde für Pfade im Linux-Stil (nur mit Schrägstrich) entwickelt. Insbesondere wird der umgekehrte Schrägstrich als Escape-Zeichen verwendet, sodass Pfade im Windows-Stil nicht einfach akzeptiert werden können. Meine C # -Version behält dieses Verhalten bei.

Um dies zu unterdrücken und sowohl umgekehrte Schrägstriche als auch Schrägstriche als Pfadtrennzeichen (in Mustern oder Eingaben) zuzulassen, setzen Sie die Option AllowWindowsPaths:

var mm = new Minimatcher(searchPattern, new Options { AllowWindowsPaths = true });

Wenn Sie diese Option übergeben, werden Fluchtzeichen vollständig deaktiviert.

Nuget:http://www.nuget.org/packages/Minimatch/

GitHub:https://github.com/SLaks/Minimatch

1
vulcan raven

Die Eigenschaften "Name" sind gleich. Nehmen:

DirectoryInfo dir1 = new DirectoryInfo("C:\\Scratch");
DirectoryInfo dir2 = new DirectoryInfo("C:\\Scratch\\");
DirectoryInfo dir3 = new DirectoryInfo("C:\\Scratch\\4760");
DirectoryInfo dir4 = new DirectoryInfo("C:\\Scratch\\4760\\..\\");

dir1.Name == dir2.Name and dir2.Name == dir4.Name ("Scratch" in diesem Fall. dir3 == "4760".) Nur die FullName-Eigenschaften unterscheiden sich.

Möglicherweise können Sie eine rekursive Methode ausführen, um die Name-Eigenschaften jedes übergeordneten Elements anhand Ihrer zwei DirectoryInfo-Klassen zu überprüfen, um sicherzustellen, dass der vollständige Pfad derselbe ist.

EDIT: funktioniert das für deine Situation? Erstellen Sie eine Konsolenanwendung, und fügen Sie diese über die gesamte Datei Program.cs ein. Stellen Sie der AreEquals () - Funktion zwei DirectoryInfo-Objekte zur Verfügung, und es wird True zurückgegeben, wenn sie dasselbe Verzeichnis sind. Möglicherweise können Sie diese AreEquals()-Methode zu einer Erweiterungsmethode in DirectoryInfo anpassen, wenn Sie möchten, so dass Sie einfach myDirectoryInfo.IsEquals(myOtherDirectoryInfo); ausführen können.

using System;
using System.Diagnostics;
using System.IO;
using System.Collections.Generic;

namespace ConsoleApplication3
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine(AreEqual(
                new DirectoryInfo("C:\\Scratch"),
                new DirectoryInfo("C:\\Scratch\\")));

            Console.WriteLine(AreEqual(
                new DirectoryInfo("C:\\Windows\\Microsoft.NET\\Framework"),
                new DirectoryInfo("C:\\Windows\\Microsoft.NET\\Framework\\v3.5\\1033\\..\\..")));

            Console.WriteLine(AreEqual(
                new DirectoryInfo("C:\\Scratch\\"),
                new DirectoryInfo("C:\\Scratch\\4760\\..\\..")));

            Console.WriteLine("Press ENTER to continue");
            Console.ReadLine();
        }

        private static bool AreEqual(DirectoryInfo dir1, DirectoryInfo dir2)
        {
            DirectoryInfo parent1 = dir1;
            DirectoryInfo parent2 = dir2;

            /* Build a list of parents */
            List<string> folder1Parents = new List<string>();
            List<string> folder2Parents = new List<string>();

            while (parent1 != null)
            {
                folder1Parents.Add(parent1.Name);
                parent1 = parent1.Parent;
            }

            while (parent2 != null)
            {
                folder2Parents.Add(parent2.Name);
                parent2 = parent2.Parent;
            }

            /* Now compare the lists */

            if (folder1Parents.Count != folder2Parents.Count)
            {
                // Cannot be the same - different number of parents
                return false;
            }

            bool equal = true;

            for (int i = 0; i < folder1Parents.Count && i < folder2Parents.Count; i++)
            {
                equal &= folder1Parents[i] == folder2Parents[i];
            }

            return equal;
        }
    }
}
1
Andy Shellam
bool Equals(string path1, string path2)
{
    return new Uri(path1) == new Uri(path2);
}

Uri-Konstruktor normalisiert den Pfad.

0
boris
bool equals = myDirectoryInfo1.FullName == myDirectoryInfo2.FullName;

?

0
herzmeister
using System;
using System.Collections.Generic;
using System.Text;

namespace EventAnalysis.IComparerImplementation
{

    public sealed class FSChangeElemComparerByPath : IComparer<FSChangeElem>
    {
        public int Compare(FSChangeElem firstPath, FSChangeElem secondPath)
        {
            return firstPath.strObjectPath == null ?
                (secondPath.strObjectPath == null ? 0 : -1) :
                (secondPath.strObjectPath == null ? 1 : ComparerWrap(firstPath.strObjectPath, secondPath.strObjectPath));
        }

        private int ComparerWrap(string stringA, string stringB)
        {
            int length = 0;
            int start = 0;
            List<string> valueA = new List<string>();
            List<string> valueB = new List<string>();

            ListInit(ref valueA, stringA);
            ListInit(ref valueB, stringB);

            if (valueA.Count != valueB.Count)
            {
                length = (valueA.Count > valueB.Count)
                           ? valueA.Count : valueB.Count;

                if (valueA.Count != length)
                {
                    for (int i = 0; i < length - valueA.Count; i++)
                    {
                        valueA.Add(string.Empty);
                    }
                }
                else
                {
                    for (int i = 0; i < length - valueB.Count; i++)
                    {
                        valueB.Add(string.Empty);
                    }
                }
            }

            else
                length = valueA.Count;

            return RecursiveComparing(valueA, valueB, length, start);
        }

        private void ListInit(ref List<string> stringCollection, string stringToList)
        {
            foreach (string s in stringToList.Remove(0, 2).Split('\\'))
            {
                stringCollection.Add(s);
            }
        }

        private int RecursiveComparing(List<string> valueA, List<string> valueB, int length, int start)
        {
            int result = 0;

            if (start != length)
            {
                if (valueA[start] == valueB[start])
                {
                    result = RecursiveComparing(valueA, valueB, length, ++start);
                }
                else
                {
                    result = String.Compare(valueA[start], valueB[start]);
                }
            }
            else
                return 0;

            return result;
        }
    }
}
0
Denis