最好检查长度是不是超过 MAX_PATH 或捕获 PathTooLongException?

Posted

技术标签:

【中文标题】最好检查长度是不是超过 MAX_PATH 或捕获 PathTooLongException?【英文标题】:Better to check if length exceeds MAX_PATH or catch PathTooLongException?最好检查长度是否超过 MAX_PATH 或捕获 PathTooLongException? 【发布时间】:2014-06-28 15:07:02 【问题描述】:

我正在编写一个使用System.IO 方法处理文件和目录的C# 程序。其中一些方法包括Directory.GetDirectoriesDirectory.GetFilesPath.GetDirectoryName,如果路径太长,它们都会抛出PathTooLongException 异常。我的第一个问题是 Microsoft .NET Framework 是否强制执行路径的最大长度,与在 C++ 中调用 Windows API 的方式相同吗? C# 中超过MAX_PATH 的路径(在string 中)是否会导致PathTooLongException 被抛出?

我应该使用这个吗?

string getFolderName(string path) 

    if (string.IsNullOrWhiteSpace(path))
        return string.Empty;

    if (path.Length > 260)
    
        System.Diagnostics.Debug.WriteLine("Path is too long.");
        return string.Empty;
    

    string folderName = System.IO.Path.GetDirectoryName(path);

    return folderName;

还是这个?

string getFolderName(string path) 

    if (string.IsNullOrWhiteSpace(path))
        return string.Empty;

    string folderName = string.Empty;

    try 
        folderName = System.IO.Path.GetDirectoryName(path);
    
    catch (System.IO.PathTooLongException)
    
        System.Diagnostics.Debug.WriteLine("Path is too long.");
    

    return folderName;

【问题讨论】:

你从哪里得到MAX_PATH?捕获PathTooLongException 几乎肯定会更可靠,因为它已包含在您调用的代码中。请注意,如果您不想处理异常,您甚至不需要 try/catch;让它传播给调用者。 【参考方案1】:

将值硬编码到代码中通常不是最好的主意。仅供参考,目录名称必须小于 小于248 字符,最大文件名长度必须小于 小于260 字符。如果您专门寻找过长的路径,那么您现有的代码已经存在漏洞。

question 解决了这个问题并提供了一些解决方案。如果你想为路径使用固定长度,你可以这样做

public static bool IsPathWithinLimits (string fullPathAndFilename)

     const int MAX_PATH_LENGTH = 259;//260-1
     return fullPathAndFilename.Length<=MAX_PATH_LENGTH;

您还可以使用反射来找到最大路径长度。我会使用反射来获得最大路径长度 ONCE,然后存储该变量并在后续调用中使用它。

public class PathHelper

     private static int MaxPathLength get; set;

     static PathHelper()
     
          // reflection
          FieldInfo maxPathField = typeof(Path).GetField("MaxPath", 
              BindingFlags.Static | 
              BindingFlags.GetField | 
              BindingFlags.NonPublic );

          // invoke the field gettor, which returns 260
          MaxPathLength = (int) maxPathField.GetValue(null);
         //the NUL terminator is part of MAX_PATH https://msdn.microsoft.com/en-us/library/aa365247.aspx#maxpath
               MaxPathLength--; //So decrease by 1

     


     public static bool IsPathWithinLimits (string fullPathAndFilename)
               
          return fullPathAndFilename.Length<=MaxPathLength;
     


注意:此代码未经测试。

【讨论】:

【参考方案2】:

我认为,您不确定 MAX_PATH 是如何在后台使用的这一事实表明,最好捕获异常而不是尝试自己执行检查。

我的一般理念是,实际使用数据的代码应该负责检查它是否有效。由于您的getFolderName 方法除了将其传递给GetDirectoryName 之外对path 没有任何作用,我不会费心检查长度,甚至可能不会费心检查它是否为空/空。把它传递给GetDirectoryName就可以了。

当然,这条规则也有例外。例如,如果我有一个方法接收一堆参数,然后将这些参数传递给其他各种方法,我可能想预先进行一些检查,这样我就不会陷入某种奇怪的状态,因为只有一半参数有效。

附带说明,我相信 C#(可能是所有 .NET)会自动将所有变量初始化为其默认值,因此将 folderName 初始化为 String.Empty 是多余的。

【讨论】:

“我相信 C#(可能是所有 .NET)会自动将所有变量初始化为其默认值,因此将 folderName 初始化为 String.Empty 是多余的。”。 String.Empty 不是 string 的默认值:null 是。请考虑编辑您的答案以删除误导性信息。【参考方案3】:

更好的是判断电话。

捕获异常比测试条件和完全避免异常要慢得多。但是,除非您将遇到大量异常,否则性能差异根本不重要。

很难想象会出现大量路径太长错误的情况,除非您尝试将树复制或移动到已经很深的目录节点中。在这种情况下,您最好预先测试所有内容,这样您就不会创建一个会在中间失败的大型缓慢操作。

但是,正如previous answer 所示,硬编码 260 无论如何都是个坏主意。

没有内置的 windows 功能可以为给定系统提供真正的答案,但您可以在开始操作之前通过用户系统上的反复试验(可能是二进制搜索)来简单地确定答案。

但是,如果您阅读了我引用的文章,您会发现在程序中创建比在 Windows 中运行良好的路径更容易。一旦达到 255 个字符,Windows 资源管理器就会出现问题,长话短说,如果您有任何选择,我建议最多限制为 255 个。

【讨论】:

以上是关于最好检查长度是不是超过 MAX_PATH 或捕获 PathTooLongException?的主要内容,如果未能解决你的问题,请参考以下文章

最好“尝试”一些东西并捕获异常或测试是不是可以首先避免异常?

如何创建超过 MAX_PATH 的目录

通过`getDisplayMedia`检查浏览器/平台是不是支持屏幕捕获

用于检查二进制数组是不是可以旋转到元素总和不超过 1 的快速算法

捕获“超出最大请求长度”

Boost.Filesystem 中的 MAX_PATH 限制