質問

ようにしていく静的加機能にC#アプリケーションを見つけ出ます。NETフレームワークが再場合はファイルパスのファイルシステムで指定します。

例:

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

また、次のコードを以下の多くの異なだけではなくなります。知っていWindowsは大文字と小文字を区別する一般んに渡す必要がありこれらのファイルへのパスClearCaseを考慮したファイルパスケーシングで、UnixとWindowsアプリケーション.

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;
}
役に立ちましたか?

解決

これは、ファイルとディレクトリのすべてが存在し、アクセス可能であることを前提として非常に単純な実装であります

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);
}

しかし、このバグがあります:相対パスを絶対パスに変換されます。あなたのオリジナルのコードは、上記と同じでしたので、私はあなたがこの動作をしたい行うことを仮定しています。

他のヒント

以下の動作範囲においたしまし...けのAPIの使用はございます。

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);

あなたは上のケースを取得し、検索の結果を返すようにしたいファイルを検索することができます(あなたは右、存在するファイルのケースを確認したいです?)。このような何かます:

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

あなたが探しているもの、このですか?

私は、より効率的な何かを持っていますが、ます:

1)すべてのケースのために動作するようには思えません。 (私はそれが正しくケーシングを取得し、それがないものを、どのファイルやディレクトリのパターンを考え出していませんでした。)

2)これは、Windowsの特定のです。

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);

上記@Antsによって答えはの絶対の受け入れ答えとしてクレジットを取得する必要があります。しかし、私は自分の目的にそれを少しリファクタリング。アプローチはFileInfoオブジェクトとDirectoryInfoのための拡張メソッドとしてパッケージされており、リターンは同様のものを修正します。

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];
}

私は、FileInfoオブジェクトといくつかのケース矛盾の問題上で、私の頭を叩いてきました。パスの比較や保存を行う際に堅牢性を確保するために、私はすべて大文字に変換します。コードの意図を明確にするために、私はまた、これらの拡張メソッドを持っています:

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

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

あなたはあなたのためのファイルを見つけるために、システムをお勧めします。私は正確なパスを、すなわち、知っているシステムを持っていないことをふりをすることによってこれを行うの検索

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

だから我々は、正確なファイル名をフィルタリングし、現在のディレクトリのみ(再帰なし)に検索を制限し、ディレクトリで検索します。

これは、(ファイルが存在しない場合)は、単一のファイル正しいケーシングのパス(ファイルが存在する場合)、または何のいずれかを含む文字配列を返します。

一つの警告:あなたはこのアプローチは、それらを受け入れるため、入力パスにワイルドカードを禁止する必要があり、結果として、複数のファイルを見つけることができます。

編集

ドライブ文字は、まだ私たちが提供するケーシングをたどるように思われます。また、これは、UNCパスを試験する必要があります。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top