I am trying to determine whether a string input by a user is valid for representing a path to a folder. By valid, I mean formatted properly.
In my application, the f
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;
}
Call Path.GetFullPath; it will throw exceptions if the path is invalid.
To disallow relative paths (such as Word
), call Path.IsPathRooted.
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;
}
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.
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:").
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))
{
...
}