Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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.


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.


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.


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

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