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

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

在我的应用程序中,该文件夹表示一个安装目的地。假设文件夹路径 有效,我想确定该文件夹是否存在,如果不存在则创建它。

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

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

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

一个正则表达式与 Directory.Exists()相结合的测试,是否会给我一个 很好方法来检查路径是否有效以及它是否存在?我知道这将随着操作系统和其他因素的不同而有所不同,但是这个程序只针对 窗户用户。

156212 次浏览

Call Path.GetFullPath; it will throw exceptions if the path is invalid.

To disallow relative paths (such as Word), call Path.IsPathRooted.

Use this Code

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

I actually disagree with SLaks. That solution did not work for me. Exception did not happen as expected. But this code worked for me:

if(System.IO.Directory.Exists(path))
{
...
}
    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;
}

Path.GetFullPath gives below exceptions only

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.

Alternate way is to use the following :

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

Here is a solution that leverages the use of Path.GetFullPath as recommended in the answer by @SLaks.

In the code that I am including here, note that IsValidPath(string path) is designed such that the caller does not have to worry about exception handling.

You may also find that the method that it calls, TryGetFullPath(...), also has merit on its own when you wish to safely attempt to get an absolute path.

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

I haven't had any problems with this code:

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

For example these would return 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);

And these would return 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);

A simpler OS-independent solution:

Go ahead and attempt to create the actual directory; if there is an issue or the name is invalid, the OS will automatically complain and the code will throw.

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

Usage:

try
{
PathHelper.ValidatePath(path);
}
catch(Exception e)
{
// handle exception
}

Directory.CreateDirectory() will automatically throw in all of the following situations:

System.IO.IOException:
The directory specified by path is a file. -or- The network name is not known.

System.UnauthorizedAccessException:
The caller does not have the required permission.

System.ArgumentException:
path is a zero-length string, contains only white space, or contains one or more invalid characters. You can query for invalid characters by using the System.IO.Path.GetInvalidPathChars method. -or- path is prefixed with, or contains, only a colon character (:).

System.ArgumentNullException:
path is null.

System.IO.PathTooLongException:
The specified path, file name, or both exceed the system-defined maximum length.

System.IO.DirectoryNotFoundException:
The specified path is invalid (for example, it is on an unmapped drive).

System.NotSupportedException:
path contains a colon character (:) that is not part of a drive label ("C:").