In C# check that filename is *possibly* valid (not that it exists)

C#ValidationFile

C# Problem Overview


Is there a method in the System.IO namespace that checks the validity of a filename?

For example, C:\foo\bar would validate and :"~-* would not

Or a little trickier, X:\foo\bar would validate is there is an X: drive on the system, but wouldn't otherwise.

I suppose I could write such a method myself, but I'm more interested in a built-in one.

C# Solutions


Solution 1 - C#

Just do;

System.IO.FileInfo fi = null;
try {
  fi = new System.IO.FileInfo(fileName);
}
catch (ArgumentException) { }
catch (System.IO.PathTooLongException) { }
catch (NotSupportedException) { }
if (ReferenceEquals(fi, null)) {
  // file name is not valid
} else {
  // file name is valid... May check for existence by calling fi.Exists.
}

For creating a FileInfo instance the file does not need to exist.

Solution 2 - C#

You can get a list of invalid characters from Path.GetInvalidPathChars and GetInvalidFileNameChars as discussed in this question.

As noted by jberger, there some other characters which are not included in the response from this method. For much more details of the windows platform, take a look at Naming Files, Paths and Namespaces on MSDN.

As Micah points out, there is Directory.GetLogicalDrives to get a list of valid drives.

Solution 3 - C#

You could make use the System.Uri class. The Uri class isn't just useful for web URLs, it also handles file system paths as well. Use the Uri.TryCreate method to find if the path is rooted then use the IsLoopback property to determine if the Uri references the local machine.

Here is a simple method which determines if a string is a valid, local, and rooted file path.

public bool IsPathValidRootedLocal(String pathString) {
    Uri pathUri;
    Boolean isValidUri = Uri.TryCreate(pathString, UriKind.Absolute, out pathUri);
    return isValidUri && pathUri != null && pathUri.IsLoopback;
}

I am confident this will work.

Solution 4 - C#

There are several methods you could use that exist in the System.IO namespace:

Directory.GetLogicalDrives() // Returns an array of strings like "c:\"
Path.GetInvalidFileNameChars() // Returns an array of characters that cannot be used in a file name
Path.GetInvalidPathChars() // Returns an array of characters that cannot be used in a path.

As suggested you could then do this:

bool IsValidFilename(string testName) {
    string regexString = "[" + Regex.Escape(Path.GetInvalidPathChars()) + "]";
    Regex containsABadCharacter = new Regex(regexString);
    if (containsABadCharacter.IsMatch(testName)) {
        return false;
    }

    // Check for drive
    string pathRoot = Path.GetPathRoot(testName);
    if (Directory.GetLogicalDrives().Contains(pathRoot)) {
        // etc
    }

    // other checks for UNC, drive-path format, etc

    return true;
}

Solution 5 - C#

Thought I would post a solution I cobbled together from bits of answers I found after searching for a robust solution to the same problem. Hopefully it helps someone else.

using System;
using System.IO;
//..

public static bool ValidateFilePath(string path, bool RequireDirectory, bool IncludeFileName, bool RequireFileName = false)
{
    if (string.IsNullOrEmpty(path)) { return false; }
    string root = null;
    string directory = null;
    string filename = null;
    try
    {
        // throw ArgumentException - The path parameter contains invalid characters, is empty, or contains only white spaces.
        root = Path.GetPathRoot(path);

        // throw ArgumentException - path contains one or more of the invalid characters defined in GetInvalidPathChars.
        // -or- String.Empty was passed to path.
        directory = Path.GetDirectoryName(path);

        // path contains one or more of the invalid characters defined in GetInvalidPathChars
        if (IncludeFileName) { filename = Path.GetFileName(path); }
    }
    catch (ArgumentException)
    {
        return false;
    }

    // null if path is null, or an empty string if path does not contain root directory information
    if (String.IsNullOrEmpty(root)) { return false; }

    // null if path denotes a root directory or is null. Returns String.Empty if path does not contain directory information
    if (String.IsNullOrEmpty(directory)) { return false; }

    if (RequireFileName)
    {
        // if the last character of path is a directory or volume separator character, this method returns String.Empty
        if (String.IsNullOrEmpty(filename)) { return false; }

        // check for illegal chars in filename
        if (filename.IndexOfAny(Path.GetInvalidFileNameChars()) >= 0) { return false; }
    }
    return true;
}

Solution 6 - C#

Even if the filename is valid, you may still want to touch it to be sure the user has permission to write.

If you won't be thrashing the disk with hundreds of files in a short period of time, I think creating an empty file is a reasonable approach.

If you really want something lighter, like just checking for invalid chars, then compare your filename against Path.GetInvalidFileNameChars().

Solution 7 - C#

Use the static GetInvalidFileNameChars method on the Path class in the System.IO namespace to determine what characters are illegal in a file name.

To do so in a path, call the static GetInvalidPathChars method on the same class.

To determine if the root of a path is valid, you would call the static GetPathRoot method on the Path class to get the root, then use the Directory class to determine if it is valid. Then you can validate the rest of the path normally.

Solution 8 - C#

Several of the System.IO.Path methods will throw exceptions if the path or filename is invalid:

  • Path.IsPathRooted()
  • Path.GetFileName()

http://msdn.microsoft.com/en-us/library/system.io.path_methods.aspx

Solution 9 - C#

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

Solution 10 - C#

I don't know of anything out of the box that can just validate all of that for you, however the Path class in .NET can help you out tremendously.

For starters, it has:

char[] invalidChars = Path.GetInvalidFileNameChars(); //returns invalid charachters

or:

Path.GetPathRoot(string); // will return the root.

Solution 11 - C#

I've had luck using regular expressions as others have shown.

One thing to keep in mind is that Windows at least prohibits some filenames that otherwise containlegal characters. A few come to mind: com, nul, prn.

I don't have it with me now, but I have a regex that takes these filename into consideration. If you want I can post it, otherwise I'm sure you can find it the same way I did: Google.

-Jay

Solution 12 - C#

Probably the bast way is to build a custom method mixing a combination of regex and small look up on your file system (to see the drives, for example)

Solution 13 - C#

This will get you the drives on the machine:

System.IO.DriveInfo.GetDrives()

These two methods will get you the bad characters to check:

System.IO.Path.GetInvalidFileNameChars();
System.IO.Path.GetInvalidPathChars();

Solution 14 - C#

Think it's too late to answer but... :) in case of path with volume name you could write something like this:

using System;
using System.Linq;
using System.IO;

// ...
    
var drives = Environment.GetLogicalDrives();
var invalidChars = Regex.Replace(new string(Path.GetInvalidFileNameChars()), "[\\\\/]", "");
var drive = drives.FirstOrDefault(d => filePath.StartsWith(d));
if (drive != null) {
    var fileDirPath = filePath.Substring(drive.Length);
    if (0 < fileDirPath.Length) {
        if (fileDirPath.IndexOfAny(invalidChars.ToCharArray()) == -1) {
            if (Path.Combine(drive, fileDirPath) != drive) {
                // path correct and we can proceed
            }
        }
    }
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionscruView Question on Stackoverflow
Solution 1 - C#mmmmmmmmView Answer on Stackoverflow
Solution 2 - C#Eugene KatzView Answer on Stackoverflow
Solution 3 - C#LamdaComplexView Answer on Stackoverflow
Solution 4 - C#MicahView Answer on Stackoverflow
Solution 5 - C#EnisleView Answer on Stackoverflow
Solution 6 - C#Michael HarenView Answer on Stackoverflow
Solution 7 - C#casperOneView Answer on Stackoverflow
Solution 8 - C#shackettView Answer on Stackoverflow
Solution 9 - C#vCillusionView Answer on Stackoverflow
Solution 10 - C#BFreeView Answer on Stackoverflow
Solution 11 - C#Jay RiggsView Answer on Stackoverflow
Solution 12 - C#tanathosView Answer on Stackoverflow
Solution 13 - C#Austin SalonenView Answer on Stackoverflow
Solution 14 - C#QgecNickView Answer on Stackoverflow