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


84

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

在我的应用程序中,该文件夹代表安装目的地。提供的文件夹路径有效的,我想,以确定是否该文件夹存在,如果它不创建它。

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

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

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

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


1
如果在Directory.Exists之后返回false时将不创建目录,这是否很好地表明用户提供了错误的输入?
罗伯特·哈维



2
@RobertI看到了这个问题,除了一般规则外,它没有提供具体的答案。第二高的答案不涉及格式设置,仅涉及无效字符。Directory.Exists方法也可以返回false,但是由于我想选择在现场创建文件夹的选项,因此我不能仅仅这样做。
Pudpuduk

@Robert在您链接的第二个主题上-输入单个单词仍会通过该问题的答案中给出的验证。
Pudpuduk

Answers:


116

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

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


我知道有更简单的东西!谢谢,我没有想到路径相对问题。
Pudpuduk

2
感谢SLaks。我已经看到很多重复项,并进行了多次Google搜索(不止一次),但这是我第一次看到对这个特定问题的很好的答案。
罗伯特·哈维

5
Path.GetFullPath(“ con.txt”)是有效的文件名。
Christoffer

8
@Slaks这太老了,不能发表评论,但是我仍然想在这里留下一个,因为我给了我-1票。Path.GetFullPath()似乎可以正常工作,但是如果路径为:“ Z:\\\\\\\\ Hi \\\\\\ There”,那不是有效的绝对路径,而是Path.GetFullPath (...)给出结果:Z:\ Hi \那里,没有引发异常。我必须通过比较GetFullPath()返回的字符串和原始字符串来对它进行一些更改,例如:private bool IsPathValid(string path){try {string fullPath = Path.GetFullPath(path); 返回fullPath == path; } catch {return false;}}
国王

4
@KingKing从unix.stackexchange.com上的Linux答案“允许多个斜杠,并且等效于单个斜杠。对于这方面的证据,在命令提示符下,试试这个:cd C:\\\\\\\Windows\\\\\\\System32。对于Windows,我无法找到记录此行为的权威信息,但是当然欢迎使用指向该行为的指针。
DavidRR

20

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

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

62
有效路径不一定是存在的目录...这正是这里要问的问题
Benlitz

1
问题与路径字符串的验证有关,该路径可能不存在。
Mubashar 2013年

我认为这种方式是正确的。不应有例外。此方法还会检查给定路径中的不正确字符。
Eugene Maksimov

如果由于Directory.Exists需要有效路径而找不到“路径”,则此条件本身将引发异常。
Fawad Surosh M.

完全错误的答案!我不知道它如何收到32个投票(截止到现在)。必须由那些在错误的地方寻找他们所面临的问题的人,他们偶然发现了这个问题。
–SнаđошƒаS

13

Path.GetFullPath仅给出以下异常

ArgumentException路径是一个零长度的字符串,仅包含空格,或包含GetInvalidPathChars中定义的一个或多个无效字符。-或者-系统无法检索绝对路径。

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

ArgumentNullException路径为null。

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

9

这是一种利用@SLaks答案中所建议的Path.GetFullPath的使用的解决方案。

在代码中,我这里有包括,注意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;
}

6

使用此代码

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

4
完成相同任务的代码略短: Path.GetInvalidFileNameChars().Any(DirectoryName.Contains) || DirectoryName == "con"
bsegraves 2012年

2
@nawfal确实。从MSDN上的命名文件,路径和命名空间中:“请勿将以下保留名称用作文件名:CON,PRN,AUX,NUL,COM1,COM2,COM3,COM4,COM5,COM6,COM7,COM8, COM9,LPT1,LPT2,LPT3,LPT4,LPT5,LPT6,LPT7,LPT8和LPT9。也请避免使用这些名称后跟扩展名;例如,不建议使用NUL.txt。有关更多信息,请参阅命名空间
DavidRR

:这个“黑名单的形式给出了”不每个Windows系统上运行,例如,当一个象形图显示了en.wikipedia.org/wiki/Miscellaneous_Symbols_and_Pictographs

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

3

这段代码没有任何问题:

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

0

一个更简单的独立于OS的解决方案。

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:
路径是长度为零的字符串,仅包含空格,或包含一个或多个无效字符。您可以使用System.IO.Path.GetInvalidPathChars方法查询无效字符。-或-path仅以冒号(:)开头或包含。

System.ArgumentNullException:
路径为null。

System.IO.PathTooLongException:
指定的路径,文件名或两者都超出系统定义的最大长度。

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

System.NotSupportedException:
路径包含不属于驱动器标签(“ C:”)的冒号(:)。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.