60

I would like to know how to determine whether string is valid file path.

The file path may or may not exist.

DavidRR
  • 18,291
  • 25
  • 109
  • 191
Diskdrive
  • 18,107
  • 27
  • 101
  • 167
  • 1
    Are you saying that you have a string that looks like a path, and whether or not the file actually exists, you want to know if a file at the given "path" could exist? If the path is valid, even if there's no file at that location? – SqlRyan Jun 18 '10 at 06:00
  • possible duplicate of [How check if given string is legal (allowed) file name under Windows?](http://stackoverflow.com/questions/62771/how-check-if-given-string-is-legal-allowed-file-name-under-windows) – nawfal Jun 05 '13 at 11:52
  • If your concern is more generally testing whether a string can represent a file ***or*** a folder, see [this answer](http://stackoverflow.com/a/3137165/1497596) or [this related answer](http://stackoverflow.com/a/41049011/1497596). – DavidRR Dec 08 '16 at 21:33

10 Answers10

73

You can use the FileInfo constructor. It will throw a ArgumentException if "The file name is empty, contains only white spaces, or contains invalid characters." It can also throw SecurityException or UnauthorizedAccessException, which I think you can ignore if you're only concerned about format.

Another option is to check against Path.GetInvalidPathChars directly. E.g.:

boolean possiblePath = pathString.IndexOfAny(Path.GetInvalidPathChars()) == -1;
Matthew Flaschen
  • 278,309
  • 50
  • 514
  • 539
  • 3
    FWIW, this will return false positives. You'll also need to check permissions and that the folder/filename isn't one of the illegal ones ( http://en.wikipedia.org/wiki/DOS#Reserved_device_names ). – Noon Silk Jun 18 '10 at 08:17
  • `new FileInfo("test")` is perfectly valid, but is not a file. – Julien Aug 11 '17 at 20:45
  • 5
    @Julien If you don't pass in a full path, it will treat it as a relative path from whatever is returned by `Directory.GetCurrentDirectory()`. So if you're working in `C:\Temp` and you call `new FileInfo("test");`, the `FullName` property will be `C:\Temp\test`. – tehDorf Nov 08 '17 at 19:53
  • The `FileInfo` constructor will also throw `NotSupportedException` – Ralt Jul 03 '18 at 08:53
  • 3
    Note that this no longer works for .NET Core / .NET 5+. The docs now say "ArgumentException: **.NET Framework and .NET Core versions older than 2.1**: The file name is empty, contains only white spaces, or contains invalid characters." I've tried it with .NET 6 and sure enough it doesn't throw an exception for a path with invalid characters. As far as I can see this is because Linux is more relaxed about valid file names than Windows, and .NET Core / .NET is now cross-platform. – Simon Elms Mar 12 '22 at 10:14
  • @SimonTewsi I came here just to say this very same thing. – rory.ap Apr 09 '22 at 18:26
28

A 100% accurate checking of a path's string format is quite difficult, since it will depend on the filesystem on which it is used (and network protocols if its not on the same computer).

Even within windows or even NTFS its not simple since it still depends on the API .NET is using in the background to communicate with the kernel.

And since most filesystems today support unicode, one might also need to check for all the rules for correcly encoded unicode, normalization, etc etc.

What I'd do is to make some basic checks only, and then handle exceptions properly once the path is used. For possible rules see:

Stefan
  • 4,187
  • 1
  • 32
  • 38
8

Here are some things you might use:

  • to check if the drive is correct (for example on one computer the drive X:\ exists, but not on yours): use Path.IsPathRooted to see if it's not a relative path and then use the drives from Environment.GetLogicalDrives() to see if your path contains one of the valid drives.
  • To check for valid characters, you have two methods: Path.GetInvalidFileNameChars() and Path.GetInvalidPathChars() which don't overlap completely. You can also use Path.GetDirectoryName(path) and Path.GetFileName(fileName) with your input name, which will throw an exception if

The path parameter contains invalid characters, is empty, or contains only white spaces.

Rox
  • 1,985
  • 12
  • 19
5

You can't really be sure until you try to create that file. Maybe the path is valid but the security settings won't allow creation of the file. The only instance that could tell you if the path is REALLY valid would be the OS, so why don't you try to create that file an catch the IOException which indicates it's not valid? In my humble opinion, this is an approach: Assume the input is valid, use it, and catch an IOException when it isn't valid.

mekb
  • 554
  • 8
  • 22
atamanroman
  • 11,607
  • 7
  • 57
  • 81
  • The question is quite clear to me and try to create that file doesn't answer to this question. *Is the string a valid file path?* – Angelo Mascaro Jul 13 '19 at 18:29
2

Try out this method which would try to cover for all the possible Exceptions scenarios. It would work for almost all the Windows related Paths.

/// <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 fewer than 248 characters, and file names must be fewer 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;
}
Marcus Mangelsdorf
  • 2,852
  • 1
  • 30
  • 40
vCillusion
  • 1,749
  • 20
  • 33
  • In this `if` branche : `if (string.IsNullOrEmpty(RelativePath))` you call `Path.GetFullPath(RelativePath);`. So it will always result of `ArgumentNullException` ? Maybe I'm wrong / doesn't fully understand, but shouldn't it be something like `path = Path.GetFullPath(path)` instead ? – TRex Dec 07 '22 at 06:56
2

Have you tried regular expressions?

^([a-zA-Z]\:)(\\[^\\/:*?<>"|]*(?<![ ]))*(\.[a-zA-Z]{2,6})$

should work

Justin L.
  • 13,510
  • 5
  • 48
  • 83
  • 4
    He never said absolute path, there's no limit to file extension length, and that's not portable. – Matthew Flaschen Jun 18 '10 at 06:04
  • 75
    Some people, when confronted with a problem, think "I know, I'll use regular expressions." Now they have two problems. -Jamie Zawinski – womp Jun 18 '10 at 06:27
1
Regex driveCheck = new Regex(@"^[a-zA-Z]:\\$");
      if (string.IsNullOrWhiteSpace(path) || path.Length < 3)
      {
        return false;
      }

      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 directoryInfo = new DirectoryInfo(Path.GetFullPath(path));
      try
      {
        if (!directoryInfo.Exists)
        {
          directoryInfo.Create();
        }
      }
      catch (Exception ex)
      {
        if (Log.IsErrorEnabled)
        {
          Log.Error(ex.Message);
        }
        return false;
      }`enter code here`

      return true;
    }
0

You can simply use Path.Combine() inside a try catch statement:

string path = @" your path ";
try
{
    Path.Combine(path);
}
catch
{
    MessageBox.Show("Invalid path");
}

Edit: Note that this function doesn't throw an exception if path contains wildcard characters ('*' and '?') since they can be used in search strings.

Jerry
  • 4,258
  • 3
  • 31
  • 58
0

I found this at regexlib.com (http://regexlib.com/REDetails.aspx?regexp_id=345) by Dmitry Borysov.

"File Name Validator. Validates both UNC (\server\share\file) and regular MS path (c:\file)"

^(([a-zA-Z]:|\\)\\)?(((\.)|(\.\.)|([^\\/:\*\?"\|<>\. ](([^\\/:\*\?"\|<>\. ])|([^\\/:\*\?"\|<>]*[^\\/:\*\?"\|<>\. ]))?))\\)*[^\\/:\*\?"\|<>\. ](([^\\/:\*\?"\|<>\. ])|([^\\/:\*\?"\|<>]*[^\\/:\*\?"\|<>\. ]))?$

Run it with a Regex.IsMatch and you'll get a bool indicating if it's valid or not. I think regular expressions is the way to go since the file may not exist.

Jonas Stensved
  • 14,378
  • 5
  • 51
  • 80
-1

The static class System.IO.Path can do what you're asking for.

Eric Anastas
  • 21,675
  • 38
  • 142
  • 236
vaitrafra
  • 666
  • 3
  • 15