关于验证:在C#中检查文件名是*可能*有效(不是它存在)

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

本问题已经有最佳答案,请猛点这里访问。

System.IO命名空间中是否有一个检查文件名有效性的方法?

例如,C:\foo\bar将验证,而:"~-*则不会

或者有点棘手,X:\foo\bar会验证系统上是否有X:驱动器,否则不会。

我想我自己可以编写这样的方法,但我对内置的方法更感兴趣。


做就是了;

1
2
3
4
5
6
7
8
9
10
11
12
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.
}

要创建FileInfo实例,不需要存在该文件。


您可以从Path.GetInvalidPathChars和GetInvalidFileNameChars中获取无效字符列表,如本问题中所述。

正如jberger所指出的,还有一些其他字符未包含在此方法的响应中。有关Windows平台的更多详细信息,请查看MSDN上的命名文件,路径和命名空间,

正如Micah指出的那样,有Directory.GetLogicalDrives来获取有效驱动器的列表。


您可以使用System.Uri类。 Uri类不仅对Web URL有用,它还处理文件系统路径。使用Uri.TryCreate方法查找路径是否为root,然后使用IsLoopback属性确定Uri是否引用本地计算机。

这是一个简单的方法,用于确定字符串是否为有效,本地和根文件路径。

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

我相信这会奏效。


您可以使用System.IO命名空间中存在的几种方法:

1
2
3
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.

如建议您可以这样做:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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;
}


即使文件名有效,您仍可能希望touch以确保用户具有写入权限。

如果你不会在短时间内用数百个文件颠倒磁盘,我认为创建一个空文件是一种合理的方法。

如果你真的想要更轻松的东西,比如检查无效的字符,那么将你的文件名与Path.GetInvalidFileNameChars()进行比较。


以为我会发布一个解决方案,我在寻找相同问题的稳健解决方案之后,从我找到的一些答案拼凑而成。希望它可以帮助别人。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
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;
}


尝试这种方法,试图涵盖所有可能的异常情况。它适用于几乎所有与Windows相关的路径。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
/// <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;
}

如果路径或文件名无效,则有几个System.IO.Path方法将抛出异常:

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

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


System.IO命名空间中的Path类上使用static GetInvalidFileNameChars方法来确定文件名中哪些字符是非法的。

要在路径中执行此操作,请在同一个类上调用静态GetInvalidPathChars方法。

要确定路径的根是否有效,可以在Path类上调用静态GetPathRoot方法来获取根,然后使用Directory类来确定它是否有效。然后,您可以正常验证路径的其余部分。


我有幸使用正则表达式,正如其他人所表明的那样。

要记住的一件事是Windows至少禁止某些文件名,否则这些文件名包含法律字符。一些想到:com,nul,prn。

我现在没有它,但我有一个正则表达式考虑这些文件名。如果你想我可以发布它,否则我相信你可以像我一样找到它:谷歌。

-Jay


我不知道开箱即用的任何东西可以为你验证所有这些,但.NET中的Path类可以帮助你。

首先,它有:

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

要么:

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


认为现在回答为时已晚,但......
如果是带有卷名的路径,你可以写这样的东西:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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
            }
        }
    }
}

这将为您提供机器上的驱动器:

1
System.IO.DriveInfo.GetDrives()

这两种方法会让你检查不好的字符:

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

可能最麻烦的方法是构建一个自定义方法,混合使用正则表达式和小文件系统的组合(例如,查看驱动器)