检查字符串是不是是有效的 Windows 目录(文件夹)路径

Posted

技术标签:

【中文标题】检查字符串是不是是有效的 Windows 目录(文件夹)路径【英文标题】:Check if a string is a valid Windows directory (folder) path检查字符串是否是有效的 Windows 目录(文件夹)路径 【发布时间】:2011-03-09 09:40:03 【问题描述】:

我正在尝试确定用户输入的字符串对于表示文件夹路径是否有效。有效是指格式正确。

在我的应用程序中,该文件夹代表一个安装目标。假设文件夹路径有效,我想判断文件夹是否存在,如果不存在就创建它。

我目前正在使用IO.Directory.Exists( String path )。我发现这很好用,除非用户没有正确格式化字符串。发生这种情况时,此方法将返回 false,表示该文件夹不存在。但这是一个问题,因为之后我将无法创建文件夹。

从我的谷歌搜索中,我发现了一个使用正则表达式来检查格式是否正确的建议。我没有使用正则表达式的经验,我想知道这是否是一种可行的方法。这是我发现的:

Regex r = new Regex( @"^(([a-zA-Z]\:)|(\\))(\\1|((\\1)[^\\]([^/:*?<>""|]*))+)$" );
return r.IsMatch( path );

能否结合Directory.Exists()进行正则表达式测试,给我一个足够好的方法来检查路径是否有效以及是否存在?我知道这会因操作系统和其他因素而异,但该程序仅针对 Windows 用户。

【问题讨论】:

如果在 Directory.Exists 返回 false 后它不会创建目录,这不是很好地表明用户提供了错误的输入吗? ***.com/questions/3067479/… ***.com/questions/422090/… @Robert我看到了这个问题,除了一般规则之外,它没有提供具体的答案。第二高的答案不包括格式,只包括无效字符。 Directory.Exists 方法也可以返回 false,但由于我想要当场创建文件夹的选项,所以我不能就这样。 @Robert 关于您链接的第二个主题 - 输入一个单词仍将通过该问题答案中给出的验证。 【参考方案1】:

致电Path.GetFullPath;如果路径无效,它会抛出异常。

要禁止相对路径(例如Word),请调用Path.IsPathRooted

【讨论】:

感谢 SLaks。我见过很多重复,并且做过很多谷歌搜索(不止一次),但这是我第一次看到这个特定问题的好答案。 Path.GetFullPath("con.txt") 是一个有效的文件名。 @Slaks 这太旧了,无法发表评论,但我仍然想在这里留下一个,因为我给了你-1 票。 Path.GetFullPath() 似乎工作正常,但如果路径是:“Z:\\\\\\\\Hi\\\\\\There”,它不是有效的绝对路径,而是 Path.GetFullPath (...) 给出结果: Z:\Hi\There 并且没有引发异常。我不得不通过比较 GetFullPath() 返回的字符串和原始字符串来稍微改变它,如下所示: private bool IsPathValid(string path) try string fullPath=Path.GetFullPath(path);返回完整路径==路径; 捕捉 返回 false; @KingKing 来自 unix.stackexchange.com 上的this Linux answer:“允许使用多个斜杠,并且等效于单个斜杠..” 我在 Windows 上观察到了同样的情况(尽管 UNC 路径中的前导斜杠可能会被区别对待)。为了证明这一点,在命令提示符下,试试这个:cd C:\\\\\\\Windows\\\\\\\System32。对于 Windows,我找不到记录此行为的权威来源,但当然欢迎提供指向。 这不会捕获所有无效路径;例如,它不会发现"c:\e:\g:\" 无效。【参考方案2】:

我实际上不同意 SLaks。该解决方案对我不起作用。异常没有按预期发生。但是这段代码对我有用:

if(System.IO.Directory.Exists(path))

    ...

【讨论】:

有效路径不一定是存在的目录......这正是这里提出的问题 问题与路径字符串的验证有关,可能不存在的路径。 我认为这种方式是正确的。不应期望异常。此方法还会检查给定路径中的错误字符。 如果发现“路径”不是真实路径,则此条件本身将引发异常,因为 Directory.Exists 需要有效路径。 完全错误的答案!我想知道它是如何获得 32 票的(截至目前)。一定是那些为他们所面临的问题寻找错误的地方的人,他们偶然发现了这一点。【参考方案3】:

Path.GetFullPath 仅给出以下例外情况

ArgumentException 路径是零长度字符串,仅包含白色 空格,或包含一个或多个在 获取无效路径字符。 - 或 - 系统无法检索绝对路径。

SecurityException 调用者没有所需的权限。

ArgumentNullException 路径为空。

NotSupportedException 路径包含不属于 卷标识符(例如,“c:\”)。

PathTooLongException 指定的路径、文件名或两者都超过 系统定义的最大长度。例如,在基于 Windows 的 平台,路径必须少于 248 个字符,文件名必须 少于 260 个字符。

另一种方法是使用以下方法:

/// <summary>
/// Validate the Path. If path is relative append the path to the project directory by default.
/// </summary>
/// <param name="path">Path to validate</param>
/// <param name="RelativePath">Relative path</param>
/// <param name="Extension">If want to check for File Path</param>
/// <returns></returns>
private static bool ValidateDllPath(ref string path, string RelativePath = "", string Extension = "")

    // Check if it contains any Invalid Characters.
    if (path.IndexOfAny(Path.GetInvalidPathChars()) == -1)
    
        try
        
            // If path is relative take %IGXLROOT% as the base directory
            if (!Path.IsPathRooted(path))
            
                if (string.IsNullOrEmpty(RelativePath))
                
                    // Exceptions handled by Path.GetFullPath
                    // ArgumentException path is a zero-length string, contains only white space, or contains one or more of the invalid characters defined in GetInvalidPathChars. -or- The system could not retrieve the absolute path.
                    // 
                    // SecurityException The caller does not have the required permissions.
                    // 
                    // ArgumentNullException path is null.
                    // 
                    // NotSupportedException path contains a colon (":") that is not part of a volume identifier (for example, "c:\"). 
                    // PathTooLongException The specified path, file name, or both exceed the system-defined maximum length. For example, on Windows-based platforms, paths must be less than 248 characters, and file names must be less than 260 characters.

                    // RelativePath is not passed so we would take the project path 
                    path = Path.GetFullPath(RelativePath);

                
                else
                
                    // Make sure the path is relative to the RelativePath and not our project directory
                    path = Path.Combine(RelativePath, path);
                
            

            // Exceptions from FileInfo Constructor:
            //   System.ArgumentNullException:
            //     fileName is null.
            //
            //   System.Security.SecurityException:
            //     The caller does not have the required permission.
            //
            //   System.ArgumentException:
            //     The file name is empty, contains only white spaces, or contains invalid characters.
            //
            //   System.IO.PathTooLongException:
            //     The specified path, file name, or both exceed the system-defined maximum
            //     length. For example, on Windows-based platforms, paths must be less than
            //     248 characters, and file names must be less than 260 characters.
            //
            //   System.NotSupportedException:
            //     fileName contains a colon (:) in the middle of the string.
            FileInfo fileInfo = new FileInfo(path);

            // Exceptions using FileInfo.Length:
            //   System.IO.IOException:
            //     System.IO.FileSystemInfo.Refresh() cannot update the state of the file or
            //     directory.
            //
            //   System.IO.FileNotFoundException:
            //     The file does not exist.-or- The Length property is called for a directory.
            bool throwEx = fileInfo.Length == -1;

            // Exceptions using FileInfo.IsReadOnly:
            //   System.UnauthorizedAccessException:
            //     Access to fileName is denied.
            //     The file described by the current System.IO.FileInfo object is read-only.-or-
            //     This operation is not supported on the current platform.-or- The caller does
            //     not have the required permission.
            throwEx = fileInfo.IsReadOnly;

            if (!string.IsNullOrEmpty(Extension))
            
                // Validate the Extension of the file.
                if (Path.GetExtension(path).Equals(Extension, StringComparison.InvariantCultureIgnoreCase))
                
                    // Trim the Library Path
                    path = path.Trim();
                    return true;
                
                else
                
                    return false;
                
            
            else
            
                return true;

            
        
        catch (ArgumentNullException)
        
            //   System.ArgumentNullException:
            //     fileName is null.
        
        catch (System.Security.SecurityException)
        
            //   System.Security.SecurityException:
            //     The caller does not have the required permission.
        
        catch (ArgumentException)
        
            //   System.ArgumentException:
            //     The file name is empty, contains only white spaces, or contains invalid characters.
        
        catch (UnauthorizedAccessException)
        
            //   System.UnauthorizedAccessException:
            //     Access to fileName is denied.
        
        catch (PathTooLongException)
        
            //   System.IO.PathTooLongException:
            //     The specified path, file name, or both exceed the system-defined maximum
            //     length. For example, on Windows-based platforms, paths must be less than
            //     248 characters, and file names must be less than 260 characters.
        
        catch (NotSupportedException)
        
            //   System.NotSupportedException:
            //     fileName contains a colon (:) in the middle of the string.
        
        catch (FileNotFoundException)
        
            // System.FileNotFoundException
            //  The exception that is thrown when an attempt to access a file that does not
            //  exist on disk fails.
        
        catch (IOException)
        
            //   System.IO.IOException:
            //     An I/O error occurred while opening the file.
        
        catch (Exception)
        
            // Unknown Exception. Might be due to wrong case or nulll checks.
        
    
    else
    
        // Path contains invalid characters
    
    return false;

【讨论】:

【参考方案4】:

这是一个利用Path.GetFullPath 使用的解决方案,正如the answer by @SLaks 中所推荐的那样。

在我在这里包含的代码中,请注意IsValidPath(string path) 的设计使得调用者不必不必担心异常处理

您可能还会发现,当您希望安全地尝试获得绝对路径时,它调用的方法TryGetFullPath(...) 本身也有其优点。

/// <summary>
/// Gets a value that indicates whether <paramref name="path"/>
/// is a valid path.
/// </summary>
/// <returns>Returns <c>true</c> if <paramref name="path"/> is a
/// valid path; <c>false</c> otherwise. Also returns <c>false</c> if
/// the caller does not have the required permissions to access
/// <paramref name="path"/>.
/// </returns>
/// <seealso cref="Path.GetFullPath"/>
/// <seealso cref="TryGetFullPath"/>
public static bool IsValidPath(string path)

    string result;
    return TryGetFullPath(path, out result);


/// <summary>
/// Returns the absolute path for the specified path string. A return
/// value indicates whether the conversion succeeded.
/// </summary>
/// <param name="path">The file or directory for which to obtain absolute
/// path information.
/// </param>
/// <param name="result">When this method returns, contains the absolute
/// path representation of <paramref name="path"/>, if the conversion
/// succeeded, or <see cref="String.Empty"/> if the conversion failed.
/// The conversion fails if <paramref name="path"/> is null or
/// <see cref="String.Empty"/>, or is not of the correct format. This
/// parameter is passed uninitialized; any value originally supplied
/// in <paramref name="result"/> will be overwritten.
/// </param>
/// <returns><c>true</c> if <paramref name="path"/> was converted
/// to an absolute path successfully; otherwise, false.
/// </returns>
/// <seealso cref="Path.GetFullPath"/>
/// <seealso cref="IsValidPath"/>
public static bool TryGetFullPath(string path, out string result)

    result = String.Empty;
    if (String.IsNullOrWhiteSpace(path))  return false; 
    bool status = false;

    try
    
        result = Path.GetFullPath(path);
        status = true;
    
    catch (ArgumentException)  
    catch (SecurityException)  
    catch (NotSupportedException)  
    catch (PathTooLongException)  

    return status;

【讨论】:

【参考方案5】:

使用此代码

string DirectoryName = "Sample Name For Directory Or File";
Path.GetInvalidFileNameChars()
  .Where(x => DirectoryName.Contains(x))
  .Count() > 0 || DirectoryName == "con"

【讨论】:

完成同样事情的略短的代码:Path.GetInvalidFileNameChars().Any(DirectoryName.Contains) || DirectoryName == "con" @nawfal 确实。来自 MSDN 上的Naming Files, Paths, and Namespaces:“不要使用以下保留名称作为文件名:CON、PRN、AUX、NUL、COM1、COM2、COM3、COM4、COM5、COM6、COM7、COM8、COM9 、LPT1、LPT2、LPT3、LPT4、LPT5、LPT6、LPT7、LPT8 和 LPT9。同时避免这些名称后跟扩展名;例如,不建议使用 NUL.txt。有关详细信息,请参阅Namespaces。 这种“黑名单方法”不适用于每个 Windows 系统,例如当出现象形文字时:en.wikipedia.org/wiki/Miscellaneous_Symbols_and_Pictographs【参考方案6】:
    private bool IsValidPath(string path)
    
        Regex driveCheck = new Regex(@"^[a-zA-Z]:\\$");
        if (!driveCheck.IsMatch(path.Substring(0, 3))) return false;
        string strTheseAreInvalidFileNameChars = new string(Path.GetInvalidPathChars());
        strTheseAreInvalidFileNameChars += @":/?*" + "\"";
        Regex containsABadCharacter = new Regex("[" + Regex.Escape(strTheseAreInvalidFileNameChars) + "]");
        if (containsABadCharacter.IsMatch(path.Substring(3, path.Length - 3)))
            return false;

        DirectoryInfo dir = new DirectoryInfo(Path.GetFullPath(path));
        if (!dir.Exists)
            dir.Create();
        return true;
    

【讨论】:

【参考方案7】:

我对这段代码没有任何问题:

private bool IsValidPath(string path, bool exactPath = true)

    bool isValid = true;

    try
    
        string fullPath = Path.GetFullPath(path);

        if (exactPath)
        
            string root = Path.GetPathRoot(path);
            isValid = string.IsNullOrEmpty(root.Trim(new char[]  '\\', '/' )) == false;
        
        else
        
            isValid = Path.IsPathRooted(path);
        
    
    catch(Exception ex)
    
        isValid = false;
    

    return isValid;

例如,这些将返回 false:

IsValidPath("C:/abc*d");
IsValidPath("C:/abc?d");
IsValidPath("C:/abc\"d");
IsValidPath("C:/abc<d");
IsValidPath("C:/abc>d");
IsValidPath("C:/abc|d");
IsValidPath("C:/abc:d");
IsValidPath("");
IsValidPath("./abc");
IsValidPath("/abc");
IsValidPath("abc");
IsValidPath("abc", false);

这些将返回 true:

IsValidPath(@"C:\\abc");
IsValidPath(@"F:\FILES\");
IsValidPath(@"C:\\abc.docx\\defg.docx");
IsValidPath(@"C:/abc/defg");
IsValidPath(@"C:\\\//\/\\/\\\/abc/\/\/\/\///\\\//\defg");
IsValidPath(@"C:/abc/def~`!@#$%^&()_-+=[];',.g");
IsValidPath(@"C:\\\\\abc////////defg");
IsValidPath(@"/abc", false);

【讨论】:

【参考方案8】:

更简单的独立于操作系统的解决方案:

继续尝试创建实际目录; 如果出现问题或名称无效,操作系统会自动抱怨并且代码会抛出。

public static class PathHelper

    public static void ValidatePath(string path)
    
        if (!Directory.Exists(path))
            Directory.CreateDirectory(path).Delete();
    

用法:

try

    PathHelper.ValidatePath(path);

catch(Exception e)

    // handle exception

Directory.CreateDirectory()会自动抛出以下所有情况:

System.IO.IOException: path 指定的目录是一个文件。 - 或 - 网络名称未知。

System.UnauthorizedAccessException: 调用者没有 所需的权限。

System.ArgumentException: path 是一个长度为零的字符串,包含 只有空格,或包含一个或多个无效字符。你 可以通过使用查询无效字符 System.IO.Path.GetInvalidPathChars 方法。 - 或 - 以路径为前缀 仅包含或包含冒号字符 (:)。

System.ArgumentNullException: 路径为空。

System.IO.PathTooLongException: 指定的路径、文件名或 都超过了系统定义的最大长度。

System.IO.DirectoryNotFoundException: 指定的路径无效 (例如,它位于未映射的驱动器上)。

System.NotSupportedException: 路径包含冒号 (:) 不是驱动器标签(“C:”)的一部分。

【讨论】:

以上是关于检查字符串是不是是有效的 Windows 目录(文件夹)路径的主要内容,如果未能解决你的问题,请参考以下文章

检查目录在 Python 中是不是有效

确定字符串输入是不是可以是 Python 中的有效目录

Nodejs检查给定的字符串是不是是有效的文件系统路径而不实际检查文件系统

如何检查字符串是不是为有效日期

检查字符串是不是是 Typescript 中的有效 JSON

使用 jq 检查字符串是不是是有效的 JSON