【问题标题】:Error: File Path is Too Long错误:文件路径太长
【发布时间】:2012-08-30 19:35:23
【问题描述】:

我正在尝试使用 C# 中的各种文件函数,例如 File.GetLastWriteTime,复制命令放置在大于 Windows 7 上允许的最大路径(即 260)的路径上的文件上。它给了我一个关于长路径名的错误。在 MSDN 支持上,他们要求在路径前使用 \\?\。我做了同样的事情,但仍然出现同样的错误,似乎没有任何改变。下面是我的代码。如果我使用正确或需要添加任何内容,请告诉我:
我作为代码使用的所有这些库还有其他东西:

以下是相应的代码:

filesToBeCopied = Directory.GetFiles(path,"*",SearchOption.AllDirectories);
for (int j = 0; j < filesToBeCopied.Length; j++)
{
    try
    {
        String filepath = @"\\?\" + filesToBeCopied[j];
        File.GetLastWriteTime(filepath);
    }
    catch (Exception ex)
    {
        MessageBox.Show("Error Inside the single file iteration for the path:" +
            filesToBeCopied[j] + " . The exception is :" + ex.Message);
    }
}

其中路径是 Windows 机器上以驱动器号开头的文件夹的路径。例如:d:\abc\bcd\cd\cdc\dc\..........

【问题讨论】:

  • 导致错误的路径是什么样的?可以贴在这里吗?
  • 这里是路径:D:\abcdefghi_abc\abcdefghis abcd abcdef company1\abcdefghis abcd abcdef company\project abcde\Do Not Delete - EP120605003\002 Image prep\Societe Generale (Open Access) - Returned 18 May 2012 (UL 30 May)\004 OCR\001 Ocr Working\003 Partition Files\4F33DBE75836ACFA95BE3B14B7BEFE5E.split
  • .Net 不支持长路径,您必须直接使用 P/Invoke 调用 API 或缩短路径。 blogs.msdn.com/b/bclteam/archive/2007/02/13/…
  • Yux,请将其发布为答案,以便我们为您投票!
  • 该链接描述了 WIN32 原生 api 的行为,.Net 自己进行验证

标签: c#


【解决方案1】:

这是您请求的至少复制部分的解决方案(谢谢pinvoke.net):

[DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
static extern bool CopyFile(string lpExistingFileName, string lpNewFileName, bool bFailIfExists);

然后实际复制您的文件:

// Don't forget the '\\?\' for long paths
string reallyLongPath = @"\\?\d:\abc\bcd\cd\cdc\dc\..........";
string destination = @"C:\some\other\path\filename.txt";
CopyFile(reallyLongPath , destination, false);

【讨论】:

    【解决方案2】:

    据我所知,如果文件路径太长,则无法直接访问文件(直接,我的意思是使用File的方法,通过构造函数创建FileInfo,或使用Directory.GetFiles(string fileName).

    我发现让您访问此类文件的唯一方法是在路径过长之前访问路径中某处的目录,然后以编程方式沿着树向下走,直到您到达您的文件,如 @ 所见987654321@.

    我从那里获取了我的代码并对其进行了一些修改,以返回一个FileInfo 对象,该对象的路径“太长”。使用此代码,您可以访问返回的FileInfo 对象(如LastWriteTime)上必要的属性但它仍然有一些限制,例如无法使用 CopyTo()OpenText() 等函数。

    // Only call GetFileWithLongPath() if the path is too long
    // ... otherwise, new FileInfo() is sufficient
    private static FileInfo GetFile(string path)
    {
        if (path.Length >= MAX_FILE_PATH)
        {
            return GetFileWithLongPath(path);
        }
        else return new FileInfo(path);
    }
    
    static int MAX_FILE_PATH = 260;
    static int MAX_DIR_PATH = 248;
    
    private static FileInfo GetFileWithLongPath(string path)
    {
        string[] subpaths = path.Split('\\');
        StringBuilder sbNewPath = new StringBuilder(subpaths[0]);
        // Build longest sub-path that is less than MAX_PATH characters 
        for (int i = 1; i < subpaths.Length; i++)
        {
            if (sbNewPath.Length + subpaths[i].Length >= MAX_DIR_PATH)
            {
                subpaths = subpaths.Skip(i).ToArray();
                break;
            }
            sbNewPath.Append("\\" + subpaths[i]);
        }
        DirectoryInfo dir = new DirectoryInfo(sbNewPath.ToString());
        bool foundMatch = dir.Exists;
        if (foundMatch)
        {
            // Make sure that all of the subdirectories in our path exist. 
            // Skip the last entry in subpaths, since it is our filename. 
            // If we try to specify the path in dir.GetDirectories(),  
            // We get a max path length error. 
            int i = 0;
            while (i < subpaths.Length - 1 && foundMatch)
            {
                foundMatch = false;
                foreach (DirectoryInfo subDir in dir.GetDirectories())
                {
                    if (subDir.Name == subpaths[i])
                    {
                        // Move on to the next subDirectory 
                        dir = subDir;
                        foundMatch = true;
                        break;
                    }
                }
                i++;
            }
            if (foundMatch)
            {
                // Now that we've gone through all of the subpaths, see if our file exists. 
                // Once again, If we try to specify the path in dir.GetFiles(),  
                // we get a max path length error. 
                foreach (FileInfo fi in dir.GetFiles())
                {
                    if (fi.Name == subpaths[subpaths.Length - 1])
                    {
                        return fi;
                    }
                }
            }
        }
        // If we didn't find a match, return null;
        return null;
    }
    

    既然你已经看到了,那就去冲洗你的眼睛并缩短你的路径。

    【讨论】:

    • 感谢乔恩,但我的问题不仅限于文件写入时间,我必须使用所有其他功能,如复制删除并创建等效目录作为其数据备份代码.....
    【解决方案3】:

    试试这段代码

    var path = Path.Combine(@"\\?\", filesToBeCopied[j]); //don't forget extension
    

    "\?\" 路径字符串的前缀告诉 Windows API 禁用所有字符串解析并将其后面的字符串直接发送到文件系统。

    重要提示:并非所有文件 I/O API 都支持“\?\”,您应该查看每个 API 的参考主题

    【讨论】:

    • 嗨,上面的代码甚至没有合并路径,因为我在消息框中显示了合并后的路径,它显示了原始路径。
    • 有人让它工作吗?使用 .NET 4.0 和 Windows 7,我无法让它与 FileFileInfoDirectoryDirectoryInfo 类一起使用。
    • AFAIK,IlSpy 告诉我 System.IO 中有一个名为 PathHelper 的私有类,不管路径长于 260 个字符时总是抛出什么。
    【解决方案4】:

    http://www.codinghorror.com/blog/2006/11/filesystem-paths-how-long-is-too-long.html

    我最近为一位超过最大路径限制 256 个字符的客户导入了一些源代码。

    您粘贴的路径长度为 285 个字符。

    正如您在评论中提到的,MSDN 的链接 (http://msdn.microsoft.com/en-us/library/aa365247%28VS.85%29.aspx#maximum%5Fpath%5Flength) 更详细地解释了这个长度:

    在 Windows API(以下段落中讨论的一些例外情况)中,路径的最大长度为 MAX_PATH,定义为 260 个字符。本地路径按以下顺序构造:驱动器号、冒号、反斜杠、由反斜杠分隔的名称组件和终止空字符。例如,驱动器 D 上的最大路径是“D:\some 256-character path string”,其中“”表示当前系统代码页的不可见终止空字符。 (这里使用字符 是为了视觉清晰,不能作为有效路径字符串的一部分。)

    关于\\?\ 功能:

    许多但不是所有文件 I/O API 都支持“\?\”;您应该查看每个 API 的参考主题以确定。

    【讨论】:

    • 感谢您的回复,但您能否告诉我是否有任何简单的解决方案或解决方法可以做到这一点,因为目前我无法更改应用程序以使用 pinvoke
    • 刚刚做了一个基本的 SO 搜索:stackoverflow.com/questions/1190614/… 选定的答案链接 (blogs.msdn.com/b/bclteam/archive/2007/02/13/…) 可能会提供一些解决方案,但显然我不能保证任何事情。 “您的里程可能会有所不同”
    猜你喜欢
    • 1970-01-01
    • 2016-09-05
    • 2016-06-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-16
    • 2016-02-29
    • 2012-08-18
    相关资源
    最近更新 更多