当前位置:  开发笔记 > 运维 > 正文

使用.NET在Windows上获取实际文件名(使用适当的大小写)

如何解决《使用.NET在Windows上获取实际文件名(使用适当的大小写)》经验,为你挑选了3个好方法。

我想和这个问题完全一样:

Windows文件系统不区分大小写.如果给定一个文件/文件夹名称(例如"somefile"),我得到该文件/文件夹的实际名称(例如,如果Explorer显示它,它应该返回"SomeFile")?

但我需要在.NET中完成它,我想要完整的路径(D:/Temp/Foobar.xml而不仅仅是Foobar.xml).

我看到FullNameFileInfo课堂上没有做到这一点.



1> Yona..:

我似乎因为NTFS不区分大小写,所以无论名称是否正确,它都将始终正确接受您的输入.

获取正确路径名的唯一方法似乎是找到像John Sibly建议的文件.

我创建了一个方法,它将获取路径(文件夹或文件)并返回它的正确套件版本(对于整个路径):

    public static string GetExactPathName(string pathName)
    {
        if (!(File.Exists(pathName) || Directory.Exists(pathName)))
            return pathName;

        var di = new DirectoryInfo(pathName);

        if (di.Parent != null) {
            return Path.Combine(
                GetExactPathName(di.Parent.FullName), 
                di.Parent.GetFileSystemInfos(di.Name)[0].Name);
        } else {
            return di.Name.ToUpper();
        }
    }

以下是一些适用于我的机器的测试用例:

    static void Main(string[] args)
    {
        string file1 = @"c:\documents and settings\administrator\ntuser.dat";
        string file2 = @"c:\pagefile.sys";
        string file3 = @"c:\windows\system32\cmd.exe";
        string file4 = @"c:\program files\common files";
        string file5 = @"ddd";

        Console.WriteLine(GetExactPathName(file1));
        Console.WriteLine(GetExactPathName(file2));
        Console.WriteLine(GetExactPathName(file3));
        Console.WriteLine(GetExactPathName(file4));
        Console.WriteLine(GetExactPathName(file5));

        Console.ReadLine();
    }

如果文件不存在,该方法将返回提供的值.

可能有更快的方法(这使用递归),但我不确定是否有任何明显的方法来做到这一点.


NTFS绝对是*敏感的*.这是Windows API与它不一致.
如果将return return di.Name.ToUpper();替换为return di.FullName.ToUpper();(FullName),它甚至可以使用UNC路径。:-)
注意:如果文件存储在网络驱动器上,则此方法不起作用。它将网络驱动器路径“ \\ myDrive”转换为MYDRIVE,这将导致路径不正确。

2> Bill Menees..:

我喜欢Yona的回答,但我希望它:

支持UNC路径

告诉我路径是否不存在

使用迭代而不是递归(因为它只使用尾递归)

最小化对Path.Combine的调用次数(以最小化字符串连接).

/// 
/// Gets the exact case used on the file system for an existing file or directory.
/// 
/// A relative or absolute path.
/// The full path using the correct case if the path exists.  Otherwise, null.
/// True if the exact path was found.  False otherwise.
/// 
/// This supports drive-lettered paths and UNC paths, but a UNC root
/// will be returned in title case (e.g., \\Server\Share).
/// 
public static bool TryGetExactPath(string path, out string exactPath)
{
    bool result = false;
    exactPath = null;

    // DirectoryInfo accepts either a file path or a directory path, and most of its properties work for either.
    // However, its Exists property only works for a directory path.
    DirectoryInfo directory = new DirectoryInfo(path);
    if (File.Exists(path) || directory.Exists)
    {
        List parts = new List();

        DirectoryInfo parentDirectory = directory.Parent;
        while (parentDirectory != null)
        {
            FileSystemInfo entry = parentDirectory.EnumerateFileSystemInfos(directory.Name).First();
            parts.Add(entry.Name);

            directory = parentDirectory;
            parentDirectory = directory.Parent;
        }

        // Handle the root part (i.e., drive letter or UNC \\server\share).
        string root = directory.FullName;
        if (root.Contains(':'))
        {
            root = root.ToUpper();
        }
        else
        {
            string[] rootParts = root.Split('\\');
            root = string.Join("\\", rootParts.Select(part => CultureInfo.CurrentCulture.TextInfo.ToTitleCase(part)));
        }

        parts.Add(root);
        parts.Reverse();
        exactPath = Path.Combine(parts.ToArray());
        result = true;
    }

    return result;
}

对于UNC路径,这会出现标题情况下的根(\\ Server\Share),而不是确切的情况,因为尝试确定远程服务器的确切案例名称和共享的确切案例名称会有很多工作.如果您对添加该支持感兴趣,则需要使用P/Invoke方法,如NetServerEnum和NetShareEnum.但这些可能很慢,并且它们不支持对服务器进行预先过滤并共享您关注的名称.

这是TryGetExactPath的单元测试方法(使用Visual Studio Testing Extensions):

[TestMethod]
public void TryGetExactPathNameTest()
{
    string machineName = CultureInfo.CurrentCulture.TextInfo.ToTitleCase(Environment.MachineName.ToLower());
    string[] testPaths = new[]
        {
            @"C:\Users\Public\desktop.ini",
            @"C:\pagefile.sys",
            @"C:\Windows\System32\cmd.exe",
            @"C:\Users\Default\NTUSER.DAT",
            @"C:\Program Files (x86)\Microsoft.NET\Primary Interop Assemblies",
            @"C:\Program Files (x86)",
            @"Does not exist",
            @"\\Nas\Main\Setups",
            @"\\Nas\Main\Setups\Microsoft\Visual Studio\VS 2015\vssdk_full.exe",
            @"\\" + machineName + @"\C$\Windows\System32\ActionCenter.dll",
            @"..",
        };
    Dictionary expectedExactPaths = new Dictionary()
        {
            { @"..", Path.GetDirectoryName(Environment.CurrentDirectory) },
        };

    foreach (string testPath in testPaths)
    {
        string lowercasePath = testPath.ToLower();
        bool expected = File.Exists(lowercasePath) || Directory.Exists(lowercasePath);
        string exactPath;
        bool actual = FileUtility.TryGetExactPath(lowercasePath, out exactPath);
        actual.ShouldEqual(expected);
        if (actual)
        {
            string expectedExactPath;
            if (expectedExactPaths.TryGetValue(testPath, out expectedExactPath))
            {
                exactPath.ShouldEqual(expectedExactPath);
            }
            else
            {
                exactPath.ShouldEqual(testPath);
            }
        }
        else
        {
            exactPath.ShouldBeNull();
        }
    }
}



3> bingles..:

受Ivan的回答启发,这里也是一种处理驱动器字母外壳的方法:

public string FixFilePathCasing(string filePath)
{
    string fullFilePath = Path.GetFullPath(filePath);

    string fixedPath = "";
    foreach(string token in fullFilePath.Split('\\'))
    {
        //first token should be drive token
        if(fixedPath == "")
        {
            //fix drive casing
            string drive = string.Concat(token, "\\");
            drive = DriveInfo.GetDrives()
                .First(driveInfo => driveInfo.Name.Equals(drive, StringComparison.OrdinalIgnoreCase)).Name;

            fixedPath = drive;
        }
        else
        {
            fixedPath = Directory.GetFileSystemEntries(fixedPath, token).First();
        }
    }

    return fixedPath;
}

推荐阅读
周扒pi
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有