21

我正在尝试用 C# 编写一个静态成员函数,或者在 .NET Framework 中找到一个将文件路径重新设置为文件系统指定的文件路径的函数。

例子:

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

6 回答 6

23

这是一个非常简单的实现,假设文件和目录都存在并且可以访问:

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

但是有一个错误:相对路径被转换为绝对路径。您上面的原始代码也是如此,所以我假设您确实想要这种行为。

于 2009-01-26T09:12:09.740 回答
3

在我测试的范围内,以下工作正常......唯一的问题是使用的 API 仅在 Vista 中可用。

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);
于 2009-01-28T12:13:28.423 回答
1

您可以搜索您想要获取案例的文件并返回搜索结果(您想要检查存在的文件的大小写,对吗?)。像这样的东西:

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

这是你要找的吗?

于 2009-01-26T04:53:41.247 回答
1

我有更有效的东西,但是:

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);
于 2009-01-28T07:19:45.880 回答
1

上面@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();
}
于 2012-08-07T22:20:04.297 回答
0

您将希望系统为您找到该文件。我通过假装我不知道确切的路径来做到这一点,即进行系统搜索

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

所以我们在目录中搜索,过滤确切的文件名并将搜索限制在当前目录(无递归)。

这将返回一个字符串数组,其中包含具有正确大小写的单个文件路径(如果文件存在)或不包含任何内容(如果文件不存在)。

一个警告:您可能需要在输入路径中禁止通配符,因为这种方法接受它们并可能因此找到多个文件。

编辑

驱动器号似乎仍然遵循我们提供的大小写。此外,这需要针对 UNC 路径进行测试。

于 2015-11-04T10:29:31.850 回答