Frage

Ich versuche, eine statische Member-Funktion in C # zu schreiben oder eine in .NET Framework finden, die einen Dateipfad werden wieder Fall zu dem, was das Dateisystem gibt.

Beispiel:

string filepath = @"C:\temp.txt";
filepath = FileUtility.RecaseFilepath(filepath);

// filepath = C:\Temp.TXT
// Where the real fully qualified filepath in the NTFS volume is C:\Temp.TXT

Ich habe den folgenden Code unter versucht, und viele Varianten davon und es funktioniert immer noch nicht. Ich weiß, Windows-Groß- und Kleinschreibung im Allgemeinen, aber ich brauche diese Dateipfade zu Clearcase passieren, den Dateipfad Gehäuse hält, da es eine Unix und Windows-Anwendung.

public static string GetProperFilePathCapitalization(string filepath)
{
    string result = "";

    try
    {
        result = Path.GetFullPath(filepath);
        DirectoryInfo dir = new DirectoryInfo(Path.GetDirectoryName(result));
        FileInfo[] fi = dir.GetFiles(Path.GetFileName(result));
        if (fi.Length > 0)
        {
            result = fi[0].FullName;
        }
    }
    catch (Exception)
    {
        result = filepath;
    }

    return result;
}
War es hilfreich?

Lösung

Dies ist eine ziemlich einfache Implementierung, die davon ausgeht, dass die Datei und Verzeichnisse existieren und sind zugänglich:

static string GetProperDirectoryCapitalization(DirectoryInfo dirInfo)
{
    DirectoryInfo parentDirInfo = dirInfo.Parent;
    if (null == parentDirInfo)
        return dirInfo.Name;
    return Path.Combine(GetProperDirectoryCapitalization(parentDirInfo),
                        parentDirInfo.GetDirectories(dirInfo.Name)[0].Name);
}

static string GetProperFilePathCapitalization(string filename)
{
    FileInfo fileInfo = new FileInfo(filename);
    DirectoryInfo dirInfo = fileInfo.Directory;
    return Path.Combine(GetProperDirectoryCapitalization(dirInfo),
                        dirInfo.GetFiles(fileInfo.Name)[0].Name);
}

Es ist ein Fehler mit diesem, aber: Relative Pfade werden in absolute Pfade umgewandelt. Ihre Original-Code oben tat das gleiche, so gehe ich davon aus, dass Sie dieses Verhalten tun wollen.

Andere Tipps

Die unten arbeitet in dem Maße fein ich getestet ... einzige Haken ist, dass die verwendete API nur in Vista verfügbar ist.

static void Main(string[] args)
{
    using (FileStream fs = File.OpenRead(@"D:\temp\case\mytest.txt"))
    {
        StringBuilder path = new StringBuilder(512);
        GetFinalPathNameByHandle(fs.SafeFileHandle.DangerousGetHandle(), path, path.Capacity, 0);
        Console.WriteLine(path.ToString());
    }
}

[DllImport("kernel32.dll", SetLastError = true)]
static extern int GetFinalPathNameByHandle(IntPtr handle, [In, Out] StringBuilder path, int bufLen, int flags);

Sie nach der Datei suchen können Sie auf den Fall erhalten möchten und die Ergebnisse Ihrer Suche zurückkehren (Sie wollen das Gehäuse einer Datei überprüfen, die vorhanden ist, nicht wahr?). So etwas wie folgt aus:

public static string GetProperFilePathCapitalization(string filepath) {
   string directoryPath = Path.GetDirectoryName(filepath);
   string[] files = Directory.GetFiles(directoryPath, Path.GetFileName(filepath));
   return files[0];
}

Ist das, was Sie suchen?

Ich habe etwas effizienter, sondern:

1) Es scheint nicht für alle Fälle zu arbeiten. (Ich habe nicht das Muster, welche Dateien und Verzeichnisse herausgefunden, es richtig das Gehäuse gelangen, und welche nicht.)

2) Es ist Windows-spezifisch.

static string GetProperFilePathCapitalization1(string filename)
{
    StringBuilder sb = new StringBuilder(260);
    int length = GetLongPathName(filename, sb, sb.Capacity);

    if (length > sb.Capacity)
    {
        sb.Capacity = length;
        length = GetLongPathName(filename, sb, sb.Capacity);
    }

    if (0 == length)
        throw new Win32Exception("GetLongPathName");

    return sb.ToString();
}

[DllImport("kernel32.dll")]
static extern int GetLongPathName(string path, StringBuilder pszPath, int cchPath);

Die Antwort von @Ants oben sollte absolut Kredit als akzeptierte Antwort bekommen. Allerdings Refactoring ich es ein bisschen meine Zwecke. Der Ansatz wird als Erweiterungsmethoden verpackt für Fileinfo und Directory und Rückkehr diejenigen, auch korrigiert.

public static DirectoryInfo GetProperCasedDirectoryInfo(this DirectoryInfo dirInfo)
{
    // Inspired by http://stackoverflow.com/a/479198/244342

    if (!dirInfo.Exists)
    {
        // Will not be able to match filesystem
        return dirInfo;
    }

    DirectoryInfo parentDirInfo = dirInfo.Parent;
    if (parentDirInfo == null)
    {
        return dirInfo;
    }
    else
    {
        return parentDirInfo.GetProperCasedDirectoryInfo().GetDirectories(dirInfo.Name)[0];
    }
}

public static FileInfo GetProperCasedFileInfo(this FileInfo fileInfo)
{
    // Inspired by http://stackoverflow.com/a/479198/244342

    if (!fileInfo.Exists)
    {
        // Will not be able to match filesystem
        return fileInfo;
    }

    return fileInfo.Directory.GetProperCasedDirectoryInfo().GetFiles(fileInfo.Name)[0];
}

Ich habe schlug meinen Kopf über einige Fall-Inkonsistenz Probleme mit Fileinfo. Um die Robustheit zu gewährleisten, konvertiere ich zu allen Caps, wenn ein Vergleich oder die Lagerung der Wege tun. Um die Absicht des Codes zu klären, ich habe auch diese Erweiterungsmethoden:

public static string GetPathForKey(this FileInfo File)
{
    return File.FullName.ToUpperInvariant();
}

public static string GetDirectoryForKey(this FileInfo File)
{
    return File.DirectoryName.ToUpperInvariant();
}

Sie werden das System die Datei für Sie zu finden. Ich tue dies, indem er vorgibt, dass ich weiß nicht, den genauen Pfad, das heißt haben das System Suche :

var fileName = Path.GetFileName(filePath);
var dir = Path.GetDirectoryName(filePath);
var filePaths = Directory.GetFiles(dir, fileName, SearchOption.TopDirectoryOnly);
var caseCorrectedFilePath = filePaths.FirstOrDefault();

So suchen wir in dem Verzeichnis, das Filtern auf den genauen Dateinamen und die Suche nach dem aktuellen Verzeichnis zu begrenzen nur (keine Rekursion).

Das gibt ein String-Array entweder den einzelnen Dateipfad mit dem richtigen Gehäusen enthält (wenn die Datei vorhanden ist) oder nichts (wenn die Datei nicht existiert).

Eine Warnung: Möglicherweise müssen Sie Platzhalter im Eingabepfad verbieten, weil dieser Ansatz sie akzeptiert und kann mehrere Dateien als Ergebnis findet

.

Bearbeiten

Der Laufwerksbuchstabe erscheint nach wie vor das Gehäuse zu folgen, die wir bieten. Außerdem muss diese für UNC-Pfade getestet werden.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top