Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/319.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#文件路径重铸_C#_.net_Filenames_Case Sensitive_Filepath - Fatal编程技术网

C#文件路径重铸

C#文件路径重铸,c#,.net,filenames,case-sensitive,filepath,C#,.net,Filenames,Case Sensitive,Filepath,我试图在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:\T

我试图在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,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;
}

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

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

这就是您想要的吗?

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

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

不过,这有一个缺陷:相对路径被转换为绝对路径。您上面的原始代码也是这样做的,因此我假设您确实想要这种行为。

我有一些更有效的方法,但是:

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

在我测试的范围内,下面的工作很好。。。唯一需要注意的是,所使用的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);

上面@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的一些案例不一致性问题绞尽脑汁。为了确保健壮性,在进行路径比较或存储时,我将转换为所有CAP。为了阐明代码的意图,我还提供了以下扩展方法:

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

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

您将希望系统为您查找该文件。我假装不知道确切的路径,即让系统搜索:

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

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

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

编辑


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

因为ClearCase。我在问题中已经说过了。Vista的好解决方案。请注意,这会解析符号链接。请参阅中的备注:不幸的是,这会在UNC路径上中断。我需要它在UNC路径上工作。比如\\SERVERNAME\Hostdir\MyDocument.docxI,我将把它作为答案。为了我的需要,它工作得最好。我可以在这个黑客的基础上添加额外的黑客来让它工作,但事实证明,由于复杂的原因,我放弃了这个功能。我发现
dirInfo.Name
对于UNC共享是完全错误的,因为它删除了服务器名。就我而言,
dirInfo.FullName.ToUpperInvariant()
已经足够好了-它不能恢复共享名的正确大小写,但它确实构造了一个有效的路径。要使它使用网络共享或UNC路径,请使用“return dirInfo.Root.FullName;”而不是“return dirInfo.name;”。使用UNC路径、网络路径和正常路径进行测试。仅当文件存在时才会出现这种情况。否则没关系,你不这样认为吗?这会修复文件的大小写,但路径的其余部分仍然不正确地大小写。
var fileName = Path.GetFileName(filePath);
var dir = Path.GetDirectoryName(filePath);
var filePaths = Directory.GetFiles(dir, fileName, SearchOption.TopDirectoryOnly);
var caseCorrectedFilePath = filePaths.FirstOrDefault();