如何检查给定的字符串是否在Windows下是合法的/有效的文件名?

时间:2021-12-08 21:22:18

I want to include a batch file rename functionality in my application. A user can type a destination filename pattern and (after replacing some wildcards in the pattern) I need to check if it's going to be a legal filename under Windows. I've tried to use regular expression like [a-zA-Z0-9_]+ but it doesn't include many national-specific characters from various languages (e.g. umlauts and so on). What is the best way to do such a check?

我想在我的应用程序中包含一个批处理文件重命名功能。用户可以输入目标文件名模式(在替换模式中的一些通配符之后),我需要检查它是否是Windows下的合法文件名。我尝试过使用像[a-zA-Z0-9_]+这样的正则表达式,但它不包括许多不同语言的国家特定字符(例如,umlauts等等)。做这样的检查最好的方法是什么?

25 个解决方案

#1


92  

You can get a list of invalid characters from Path.GetInvalidPathChars and GetInvalidFileNameChars.

您可以从路径获得无效字符的列表。GetInvalidPathChars GetInvalidFileNameChars。

UPD: See Steve Cooper's suggestion on how to use these in a regular expression.

UPD:看看Steve Cooper关于如何在正则表达式中使用它们的建议。

UPD2: Note that according to the Remarks section in MSDN "The array returned from this method is not guaranteed to contain the complete set of characters that are invalid in file and directory names." The answer provided by sixlettervaliables goes into more details.

UPD2:注意,根据MSDN中的备注部分,“该方法返回的数组不能保证包含文件和目录名中无效的完整字符集。”由“六个字母”提供的答案更详细。

#2


112  

From MSDN's "Naming a File or Directory," here are the general conventions for what a legal file name is under Windows:

从MSDN的“命名文件或目录”,这里是关于在Windows下合法文件名称的一般约定:

You may use any character in the current code page (Unicode/ANSI above 127), except:

您可以在当前代码页中使用任何字符(Unicode/ANSI以上127),但是:

  • < > : " / \ | ? *
  • < >: " / \ | ?*
  • Characters whose integer representations are 0-31 (less than ASCII space)
  • 整数表示为0-31(小于ASCII空间)的字符
  • Any other character that the target file system does not allow (say, trailing periods or spaces)
  • 目标文件系统不允许的任何其他字符(例如,尾随期间或空格)
  • Any of the DOS names: CON, PRN, AUX, NUL, COM0, COM1, COM2, COM3, COM4, COM5, COM6, COM7, COM8, COM9, LPT0, LPT1, LPT2, LPT3, LPT4, LPT5, LPT6, LPT7, LPT8, LPT9 (and avoid AUX.txt, etc)
  • 任意一个DOS名称:CON, PRN, AUX, NUL, COM0, COM1, COM2, COM3, COM4, COM5, COM6, COM7, COM8, COM9, LPT0, LPT1, LPT2, LPT3, LPT4, LPT5, LPT6, LPT7, LPT8, LPT9(并且避免使用)。txt等)
  • The file name is all periods
  • 文件名是所有的句点

Some optional things to check:

一些可选的检查事项:

  • File paths (including the file name) may not have more than 260 characters (that don't use the \?\ prefix)
  • 文件路径(包括文件名)可能不超过260个字符(不使用\?\前缀)
  • Unicode file paths (including the file name) with more than 32,000 characters when using \?\ (note that prefix may expand directory components and cause it to overflow the 32,000 limit)
  • 使用\?时使用超过32,000个字符的Unicode文件路径(包括文件名)?(注意前缀可能会展开目录组件并使其超出32,000限制)

#3


59  

For .Net Frameworks prior to 3.5 this should work:

对于3.5之前的。net框架,这应该是可行的:

Regular expression matching should get you some of the way. Here's a snippet using the System.IO.Path.InvalidPathChars constant;

正则表达式匹配应该能帮您解决这个问题。这里有一个使用System.IO.Path的代码片段。InvalidPathChars常数;

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

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

    return true;
}

For .Net Frameworks after 3.0 this should work:

对于3.0之后的。net框架,这应该是可行的:

http://msdn.microsoft.com/en-us/library/system.io.path.getinvalidpathchars(v=vs.90).aspx

http://msdn.microsoft.com/en-us/library/system.io.path.getinvalidpathchars(v =应用程序). aspx

Regular expression matching should get you some of the way. Here's a snippet using the System.IO.Path.GetInvalidPathChars() constant;

正则表达式匹配应该能帮您解决这个问题。下面是一个使用System.IO.Path.GetInvalidPathChars()常量的代码片段;

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

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

    return true;
}

Once you know that, you should also check for different formats, eg c:\my\drive and \\server\share\dir\file.ext

一旦你知道这一点,你也应该检查不同的格式,例如c:\我的\驱动器和\服务器共享\dir\文件.ext

#4


25  

Try to use it, and trap for the error. The allowed set may change across file systems, or across different versions of Windows. In other words, if you want know if Windows likes the name, hand it the name and let it tell you.

尝试使用它,并捕捉错误。允许的集合可以跨文件系统或不同版本的Windows进行更改。换句话说,如果你想知道Windows是否喜欢这个名字,就把名字给它,让它告诉你。

#5


22  

This class cleans filenames and paths; use it like

这个类清除文件名和路径;喜欢使用它

var myCleanPath = PathSanitizer.SanitizeFilename(myBadPath, ' ');

Here's the code;

这里的代码;

/// <summary>
/// Cleans paths of invalid characters.
/// </summary>
public static class PathSanitizer
{
    /// <summary>
    /// The set of invalid filename characters, kept sorted for fast binary search
    /// </summary>
    private readonly static char[] invalidFilenameChars;
    /// <summary>
    /// The set of invalid path characters, kept sorted for fast binary search
    /// </summary>
    private readonly static char[] invalidPathChars;

    static PathSanitizer()
    {
        // set up the two arrays -- sorted once for speed.
        invalidFilenameChars = System.IO.Path.GetInvalidFileNameChars();
        invalidPathChars = System.IO.Path.GetInvalidPathChars();
        Array.Sort(invalidFilenameChars);
        Array.Sort(invalidPathChars);

    }

    /// <summary>
    /// Cleans a filename of invalid characters
    /// </summary>
    /// <param name="input">the string to clean</param>
    /// <param name="errorChar">the character which replaces bad characters</param>
    /// <returns></returns>
    public static string SanitizeFilename(string input, char errorChar)
    {
        return Sanitize(input, invalidFilenameChars, errorChar);
    }

    /// <summary>
    /// Cleans a path of invalid characters
    /// </summary>
    /// <param name="input">the string to clean</param>
    /// <param name="errorChar">the character which replaces bad characters</param>
    /// <returns></returns>
    public static string SanitizePath(string input, char errorChar)
    {
        return Sanitize(input, invalidPathChars, errorChar);
    }

    /// <summary>
    /// Cleans a string of invalid characters.
    /// </summary>
    /// <param name="input"></param>
    /// <param name="invalidChars"></param>
    /// <param name="errorChar"></param>
    /// <returns></returns>
    private static string Sanitize(string input, char[] invalidChars, char errorChar)
    {
        // null always sanitizes to null
        if (input == null) { return null; }
        StringBuilder result = new StringBuilder();
        foreach (var characterToTest in input)
        {
            // we binary search for the character in the invalid set. This should be lightning fast.
            if (Array.BinarySearch(invalidChars, characterToTest) >= 0)
            {
                // we found the character in the array of 
                result.Append(errorChar);
            }
            else
            {
                // the character was not found in invalid, so it is valid.
                result.Append(characterToTest);
            }
        }

        // we're done.
        return result.ToString();
    }

}

#6


21  

This is what I use:

这就是我使用的:

    public static bool IsValidFileName(this string expression, bool platformIndependent)
    {
        string sPattern = @"^(?!^(PRN|AUX|CLOCK\$|NUL|CON|COM\d|LPT\d|\..*)(\..+)?$)[^\x00-\x1f\\?*:\"";|/]+$";
        if (platformIndependent)
        {
           sPattern = @"^(([a-zA-Z]:|\\)\\)?(((\.)|(\.\.)|([^\\/:\*\?""\|<>\. ](([^\\/:\*\?""\|<>\. ])|([^\\/:\*\?""\|<>]*[^\\/:\*\?""\|<>\. ]))?))\\)*[^\\/:\*\?""\|<>\. ](([^\\/:\*\?""\|<>\. ])|([^\\/:\*\?""\|<>]*[^\\/:\*\?""\|<>\. ]))?$";
        }
        return (Regex.IsMatch(expression, sPattern, RegexOptions.CultureInvariant));
    }

The first pattern creates a regular expression containing the invalid/illegal file names and characters for Windows platforms only. The second one does the same but ensures that the name is legal for any platform.

第一个模式创建一个正则表达式,其中只包含Windows平台的无效/非法文件名和字符。第二种方法也是这样做的,但是要确保名称对任何平台都是合法的。

#7


17  

One corner case to keep in mind, which surprised me when I first found out about it: Windows allows leading space characters in file names! For example, the following are all legal, and distinct, file names on Windows (minus the quotes):

我第一次发现它的时候,我很惊讶:Windows允许文件名中的空格字符!例如,下列文件在Windows上都是合法的、不同的文件名(减去引号):

"file.txt"
" file.txt"
"  file.txt"

One takeaway from this: Use caution when writing code that trims leading/trailing whitespace from a filename string.

这里的一个要点是:在编写从filename字符串中引入/拖尾空格的代码时要小心。

#8


8  

Rather than explicitly include all possible characters, you could do a regex to check for the presence of illegal characters, and report an error then. Ideally your application should name the files exactly as the user wishes, and only cry foul if it stumbles across an error.

与其显式地包含所有可能的字符,不如使用regex检查是否存在非法字符,然后报告错误。理想情况下,应用程序应该按照用户的意愿来命名文件,只有在遇到错误时才会发出错误的叫声。

#9


7  

Microsoft Windows: Windows kernel forbids the use of characters in range 1-31 (i.e., 0x01-0x1F) and characters " * : < > ? \ |. Although NTFS allows each path component (directory or filename) to be 255 characters long and paths up to about 32767 characters long, the Windows kernel only supports paths up to 259 characters long. Additionally, Windows forbids the use of the MS-DOS device names AUX, CLOCK$, COM1, COM2, COM3, COM4, COM5, COM6, COM7, COM8, COM9, CON, LPT1, LPT2, LPT3, LPT4, LPT5, LPT6, LPT7, LPT8, LPT9, NUL and PRN, as well as these names with any extension (for example, AUX.txt), except when using Long UNC paths (ex. \.\C:\nul.txt or \?\D:\aux\con). (In fact, CLOCK$ may be used if an extension is provided.) These restrictions only apply to Windows - Linux, for example, allows use of " * : < > ? \ | even in NTFS.

Microsoft Windows: Windows内核禁止使用范围为1-31的字符。, 0x01-0x1F)和字符" *:< > ?\ |。虽然NTFS允许每个路径组件(目录或文件名)长度为255个字符,路径长度为32767个字符,但是Windows内核只支持长度为259个字符的路径。此外,Windows禁止使用ms - dos辅助设备名称,钟元,COM1、COM2、COM3 COM4为,COM5,COM6,COM7,COM8,COM9,案子,LPT1,LPT2,LPT3,LPT4,LPT5,LPT6,LPT7,LPT8,LPT9,NUL和打印,以及这些名称与任何扩展(例如,AUX.txt),除非使用长UNC路径(交货。\ \ C:\空。txt或者\ ? \ D:\辅助\ con)。(事实上,如果提供了扩展,则可以使用时钟$。)这些限制只适用于Windows - Linux,例如,允许使用“*:< > ?即使在NTFS中也可以使用|。

Source: http://en.wikipedia.org/wiki/Filename

来源:http://en.wikipedia.org/wiki/Filename

#10


6  

Also CON, PRN, AUX, NUL, COM# and a few others are never legal filenames in any directory with any extension.

还有CON, PRN, AUX, NUL, COM#和其他一些在任何扩展名的目录中都不是合法的文件名。

#11


6  

Simplifying the Eugene Katz's answer:

简化尤金·卡茨的回答:

bool IsFileNameCorrect(string fileName){
    return !fileName.Any(f=>Path.GetInvalidFileNameChars().Contains(f))
}

Or

bool IsFileNameCorrect(string fileName){
    return fileName.All(f=>!Path.GetInvalidFileNameChars().Contains(f))
}

#12


5  

The question is are you trying to determine if a path name is a legal windows path, or if it's legal on the system where the code is running.? I think the latter is more important, so personally, I'd probably decompose the full path and try to use _mkdir to create the directory the file belongs in, then try to create the file.

问题是,您是在尝试确定路径名是合法的windows路径,还是在代码运行的系统上,它是合法的?我认为后者更重要,所以就我个人而言,我可能会分解完整的路径并尝试使用_mkdir来创建文件所属的目录,然后尝试创建文件。

This way you know not only if the path contains only valid windows characters, but if it actually represents a path that can be written by this process.

这样,您不仅知道路径是否只包含有效的windows字符,而且如果它实际上表示一个可以由这个过程编写的路径。

#13


5  

I use this to get rid of invalid characters in filenames without throwing exceptions:

我使用这个来删除文件名中的无效字符,而不抛出异常:

private static readonly Regex InvalidFileRegex = new Regex(
    string.Format("[{0}]", Regex.Escape(@"<>:""/\|?*")));

public static string SanitizeFileName(string fileName)
{
    return InvalidFileRegex.Replace(fileName, string.Empty);
}

#14


4  

From MSDN, here's a list of characters that aren't allowed:

从MSDN,这里有一个不允许的字符列表:

Use almost any character in the current code page for a name, including Unicode characters and characters in the extended character set (128–255), except for the following:

在当前代码页中几乎任何字符都可用于名称,包括扩展字符集(128-255)中的Unicode字符和字符,但以下情况除外:

  • The following reserved characters are not allowed: < > : " / \ | ? *
  • 以下保留字符不允许:< >:" / \ | ?*
  • Characters whose integer representations are in the range from zero through 31 are not allowed.
  • 不允许字符的整数表示在0到31之间。
  • Any other character that the target file system does not allow.
  • 目标文件系统不允许的任何其他字符。

#15


3  

To complement the other answers, here are a couple of additional edge cases that you might want to consider.

为了补充其他的答案,这里有一些您可能需要考虑的附加边界情况。

  • Excel can have problems if you save a workbook in a file whose name contains the '[' or ']' characters. See http://support.microsoft.com/kb/215205 for details.

    如果您将工作簿保存在名称包含“['或']字符的文件中,Excel可能会出现问题。有关详细信息,请参阅http://support.microsoft.com/kb/215205。

  • Sharepoint has a whole additional set of restrictions. See http://support.microsoft.com/kb/905231 for details.

    Sharepoint有一整套附加的限制。有关详细信息,请参阅http://support.microsoft.com/kb/905231。

#16


2  

Also the destination file system is important.

目标文件系统也很重要。

Under NTFS, some files can not be created in specific directories. E.G. $Boot in root

在NTFS下,一些文件不能在特定的目录中创建。如引导美元的根

#17


2  

This is an already answered question, but just for the sake of "Other options", here's a non-ideal one:

这是一个已经回答过的问题,但为了“其他选择”,这里有一个非理想的选项:

(non-ideal because using Exceptions as flow control is a "Bad Thing", generally)

(不理想,因为使用异常作为流控制通常是一件“坏事”)

public static bool IsLegalFilename(string name)
{
    try 
    {
        var fileInfo = new FileInfo(name);
        return true;
    }
    catch
    {
        return false;
    }
}

#18


2  

Regular expressions are overkill for this situation. You can use the String.IndexOfAny() method in combination with Path.GetInvalidPathChars() and Path.GetInvalidFileNameChars().

对于这种情况,正则表达式是多余的。可以将String.IndexOfAny()方法与Path.GetInvalidPathChars()和Path.GetInvalidFileNameChars()结合使用。

Also note that both Path.GetInvalidXXX() methods clone an internal array and return the clone. So if you're going to be doing this a lot (thousands and thousands of times) you can cache a copy of the invalid chars array for reuse.

还要注意,Path.GetInvalidXXX()方法都克隆一个内部数组并返回克隆。如果你要做很多次(成千上万次)你可以缓存一个无效chars数组的副本以供重用。

#19


1  

Windows filenames are pretty unrestrictive, so really it might not even be that much of an issue. The characters that are disallowed by Windows are:

Windows文件名是非常没有限制的,所以它甚至可能不是那么大的问题。Windows不允许的字符是:

\ / : * ? " < > |

You could easily write an expression to check if those characters are present. A better solution though would be to try and name the files as the user wants, and alert them when a filename doesn't stick.

您可以轻松地编写一个表达式来检查这些字符是否存在。不过,更好的解决方案是尝试并按用户的要求命名文件,并在文件名不稳定时发出警告。

#20


1  

If you're only trying to check if a string holding your file name/path has any invalid characters, the fastest method I've found is to use Split() to break up the file name into an array of parts wherever there's an invalid character. If the result is only an array of 1, there are no invalid characters. :-)

如果您只是想检查保存文件名/路径的字符串是否有任何无效字符,那么我找到的最快的方法是使用Split()将文件名分解为一个部分数组,只要有无效字符。如果结果仅为1的数组,则没有无效字符。:-)

var nameToTest = "Best file name \"ever\".txt";
bool isInvalidName = nameToTest.Split(System.IO.Path.GetInvalidFileNameChars()).Length > 1;

var pathToTest = "C:\\My Folder <secrets>\\";
bool isInvalidPath = pathToTest.Split(System.IO.Path.GetInvalidPathChars()).Length > 1;

I tried running this and other methods mentioned above on a file/path name 1,000,000 times in LinqPad.

我在LinqPad中尝试在一个文件/路径名上运行这个和上面提到的其他方法1,000,000次。

Using Split() is only ~850ms.

使用Split()仅为~850ms。

Using Regex("[" + Regex.Escape(new string(System.IO.Path.GetInvalidPathChars())) + "]") is around 6 seconds.

使用正则表达式(“[”+正则表达式。Escape(新字符串System.IO.Path.GetInvalidPathChars()) +“]”)大约是6秒。

The more complicated regular expressions fair MUCH worse, as do some of the other options, like using the various methods on the Path class to get file name and let their internal validation do the job (most likely due to the overhead of exception handling).

更复杂的正则表达式会更糟,其他一些选项也是如此,比如使用Path类上的各种方法来获取文件名,并让它们的内部验证来完成这项工作(最可能的原因是异常处理的开销)。

Granted it's not very often you need to validation 1 million file names, so a single iteration is fine for most of these methods anyway. But it's still pretty efficient and effective if you're only looking for invalid characters.

当然,您通常不需要验证100万个文件名,因此,对于大多数这些方法来说,一次迭代都是可以的。但是如果你只寻找无效的字符,它仍然是非常有效的。

#21


1  

My attempt:

我的尝试:

using System.IO;

static class PathUtils
{
  public static string IsValidFullPath([NotNull] string fullPath)
  {
    if (string.IsNullOrWhiteSpace(fullPath))
      return "Path is null, empty or white space.";

    bool pathContainsInvalidChars = fullPath.IndexOfAny(Path.GetInvalidPathChars()) != -1;
    if (pathContainsInvalidChars)
      return "Path contains invalid characters.";

    string fileName = Path.GetFileName(fullPath);
    if (fileName == "")
      return "Path must contain a file name.";

    bool fileNameContainsInvalidChars = fileName.IndexOfAny(Path.GetInvalidFileNameChars()) != -1;
    if (fileNameContainsInvalidChars)
      return "File name contains invalid characters.";

    if (!Path.IsPathRooted(fullPath))
      return "The path must be absolute.";

    return "";
  }
}

This is not perfect because Path.GetInvalidPathChars does not return the complete set of characters that are invalid in file and directory names and of course there's plenty more subtleties.

这并不完美,因为路径。GetInvalidPathChars不会返回文件和目录名称中无效的完整字符集,当然还有更多的细节。

So I use this method as a complement:

所以我用这个方法作为补充:

public static bool TestIfFileCanBeCreated([NotNull] string fullPath)
{
  if (string.IsNullOrWhiteSpace(fullPath))
    throw new ArgumentException("Value cannot be null or whitespace.", "fullPath");

  string directoryName = Path.GetDirectoryName(fullPath);
  if (directoryName != null) Directory.CreateDirectory(directoryName);
  try
  {
    using (new FileStream(fullPath, FileMode.CreateNew)) { }
    File.Delete(fullPath);
    return true;
  }
  catch (IOException)
  {
    return false;
  }
}

It tries to create the file and return false if there is an exception. Of course, I need to create the file but I think it's the safest way to do that. Please also note that I am not deleting directories that have been created.

如果有异常,它尝试创建文件并返回false。当然,我需要创建文件,但我认为这是最安全的方式。请注意,我没有删除已创建的目录。

You can also use the first method to do basic validation, and then handle carefully the exceptions when the path is used.

您还可以使用第一个方法进行基本的验证,然后在使用路径时仔细地处理异常。

#22


0  

I suggest just use the Path.GetFullPath()

我建议使用Path.GetFullPath()

string tagetFileFullNameToBeChecked;
try
{
  Path.GetFullPath(tagetFileFullNameToBeChecked)
}
catch(AugumentException ex)
{
  // invalid chars found
}

#23


0  

many of these answers will not work if the filename is too long & running on a pre Windows 10 environment. Similarly, have a think about what you want to do with periods - allowing leading or trailing is technically valid, but can create problems if you do not want the file to be difficult to see or delete respectively.

如果文件名太长,并且在windows10前环境中运行,那么许多这些答案都不会起作用。类似地,考虑一下您想要对句点做什么——允许前导或尾随在技术上是有效的,但是如果您不希望文件分别难于查看或删除,则可能会产生问题。

This is a validation attribute I created to check for a valid filename.

这是我创建的用于检查有效文件名的验证属性。

public class ValidFileNameAttribute : ValidationAttribute
{
    public ValidFileNameAttribute()
    {
        RequireExtension = true;
        ErrorMessage = "{0} is an Invalid Filename";
        MaxLength = 255; //superseeded in modern windows environments
    }
    public override bool IsValid(object value)
    {
        //http://*.com/questions/422090/in-c-sharp-check-that-filename-is-possibly-valid-not-that-it-exists
        var fileName = (string)value;
        if (string.IsNullOrEmpty(fileName)) { return true;  }
        if (fileName.IndexOfAny(Path.GetInvalidFileNameChars()) > -1 ||
            (!AllowHidden && fileName[0] == '.') ||
            fileName[fileName.Length - 1]== '.' ||
            fileName.Length > MaxLength)
        {
            return false;
        }
        string extension = Path.GetExtension(fileName);
        return (!RequireExtension || extension != string.Empty)
            && (ExtensionList==null || ExtensionList.Contains(extension));
    }
    private const string _sepChar = ",";
    private IEnumerable<string> ExtensionList { get; set; }
    public bool AllowHidden { get; set; }
    public bool RequireExtension { get; set; }
    public int MaxLength { get; set; }
    public string AllowedExtensions {
        get { return string.Join(_sepChar, ExtensionList); } 
        set {
            if (string.IsNullOrEmpty(value))
            { ExtensionList = null; }
            else {
                ExtensionList = value.Split(new char[] { _sepChar[0] })
                    .Select(s => s[0] == '.' ? s : ('.' + s))
                    .ToList();
            }
    } }

    public override bool RequiresValidationContext => false;
}

and the tests

和测试

[TestMethod]
public void TestFilenameAttribute()
{
    var rxa = new ValidFileNameAttribute();
    Assert.IsFalse(rxa.IsValid("pptx."));
    Assert.IsFalse(rxa.IsValid("pp.tx."));
    Assert.IsFalse(rxa.IsValid("."));
    Assert.IsFalse(rxa.IsValid(".pp.tx"));
    Assert.IsFalse(rxa.IsValid(".pptx"));
    Assert.IsFalse(rxa.IsValid("pptx"));
    Assert.IsFalse(rxa.IsValid("a/abc.pptx"));
    Assert.IsFalse(rxa.IsValid("a\\abc.pptx"));
    Assert.IsFalse(rxa.IsValid("c:abc.pptx"));
    Assert.IsFalse(rxa.IsValid("c<abc.pptx"));
    Assert.IsTrue(rxa.IsValid("abc.pptx"));
    rxa = new ValidFileNameAttribute { AllowedExtensions = ".pptx" };
    Assert.IsFalse(rxa.IsValid("abc.docx"));
    Assert.IsTrue(rxa.IsValid("abc.pptx"));
}

#24


0  

I got this idea from someone. - don't know who. Let the OS do the heavy lifting.

我是从某人那里得到这个主意的。——不知道是谁。让操作系统来承担重任。

public bool IsPathFileNameGood(string fname)
{
    bool rc = Constants.Fail;
    try
    {
        this._stream = new StreamWriter(fname, true);
        rc = Constants.Pass;
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message, "Problem opening file");
        rc = Constants.Fail;
    }
    return rc;
}

#25


0  

This check

这张支票

static bool IsValidFileName(string name)
{
    return
        !string.IsNullOrWhiteSpace(name) &&
        name.IndexOfAny(Path.GetInvalidFileNameChars()) < 0 &&
        !Path.GetFullPath(name).StartsWith(@"\\.\");
}

filters out names with invalid chars (<>:"/\|?* and ASCII 0-31), as well as reserved DOS devices (CON, NUL, COMx). It allows leading spaces and all-dot-names, consistent with Path.GetFullPath. (Creating file with leading spaces succeeds on my system).

用无效字符过滤出名称(<>:"/\|?*和ASCII 0-31),以及保留的DOS设备(CON, NUL, COMx)。它允许前导空间和所有点名,与Path.GetFullPath一致。(在我的系统上创建具有领先空间的文件)。


Used .NET Framework 4.7.1, tested on Windows 7.

使用。net Framework 4.7.1,在Windows 7上测试。

#1


92  

You can get a list of invalid characters from Path.GetInvalidPathChars and GetInvalidFileNameChars.

您可以从路径获得无效字符的列表。GetInvalidPathChars GetInvalidFileNameChars。

UPD: See Steve Cooper's suggestion on how to use these in a regular expression.

UPD:看看Steve Cooper关于如何在正则表达式中使用它们的建议。

UPD2: Note that according to the Remarks section in MSDN "The array returned from this method is not guaranteed to contain the complete set of characters that are invalid in file and directory names." The answer provided by sixlettervaliables goes into more details.

UPD2:注意,根据MSDN中的备注部分,“该方法返回的数组不能保证包含文件和目录名中无效的完整字符集。”由“六个字母”提供的答案更详细。

#2


112  

From MSDN's "Naming a File or Directory," here are the general conventions for what a legal file name is under Windows:

从MSDN的“命名文件或目录”,这里是关于在Windows下合法文件名称的一般约定:

You may use any character in the current code page (Unicode/ANSI above 127), except:

您可以在当前代码页中使用任何字符(Unicode/ANSI以上127),但是:

  • < > : " / \ | ? *
  • < >: " / \ | ?*
  • Characters whose integer representations are 0-31 (less than ASCII space)
  • 整数表示为0-31(小于ASCII空间)的字符
  • Any other character that the target file system does not allow (say, trailing periods or spaces)
  • 目标文件系统不允许的任何其他字符(例如,尾随期间或空格)
  • Any of the DOS names: CON, PRN, AUX, NUL, COM0, COM1, COM2, COM3, COM4, COM5, COM6, COM7, COM8, COM9, LPT0, LPT1, LPT2, LPT3, LPT4, LPT5, LPT6, LPT7, LPT8, LPT9 (and avoid AUX.txt, etc)
  • 任意一个DOS名称:CON, PRN, AUX, NUL, COM0, COM1, COM2, COM3, COM4, COM5, COM6, COM7, COM8, COM9, LPT0, LPT1, LPT2, LPT3, LPT4, LPT5, LPT6, LPT7, LPT8, LPT9(并且避免使用)。txt等)
  • The file name is all periods
  • 文件名是所有的句点

Some optional things to check:

一些可选的检查事项:

  • File paths (including the file name) may not have more than 260 characters (that don't use the \?\ prefix)
  • 文件路径(包括文件名)可能不超过260个字符(不使用\?\前缀)
  • Unicode file paths (including the file name) with more than 32,000 characters when using \?\ (note that prefix may expand directory components and cause it to overflow the 32,000 limit)
  • 使用\?时使用超过32,000个字符的Unicode文件路径(包括文件名)?(注意前缀可能会展开目录组件并使其超出32,000限制)

#3


59  

For .Net Frameworks prior to 3.5 this should work:

对于3.5之前的。net框架,这应该是可行的:

Regular expression matching should get you some of the way. Here's a snippet using the System.IO.Path.InvalidPathChars constant;

正则表达式匹配应该能帮您解决这个问题。这里有一个使用System.IO.Path的代码片段。InvalidPathChars常数;

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

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

    return true;
}

For .Net Frameworks after 3.0 this should work:

对于3.0之后的。net框架,这应该是可行的:

http://msdn.microsoft.com/en-us/library/system.io.path.getinvalidpathchars(v=vs.90).aspx

http://msdn.microsoft.com/en-us/library/system.io.path.getinvalidpathchars(v =应用程序). aspx

Regular expression matching should get you some of the way. Here's a snippet using the System.IO.Path.GetInvalidPathChars() constant;

正则表达式匹配应该能帮您解决这个问题。下面是一个使用System.IO.Path.GetInvalidPathChars()常量的代码片段;

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

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

    return true;
}

Once you know that, you should also check for different formats, eg c:\my\drive and \\server\share\dir\file.ext

一旦你知道这一点,你也应该检查不同的格式,例如c:\我的\驱动器和\服务器共享\dir\文件.ext

#4


25  

Try to use it, and trap for the error. The allowed set may change across file systems, or across different versions of Windows. In other words, if you want know if Windows likes the name, hand it the name and let it tell you.

尝试使用它,并捕捉错误。允许的集合可以跨文件系统或不同版本的Windows进行更改。换句话说,如果你想知道Windows是否喜欢这个名字,就把名字给它,让它告诉你。

#5


22  

This class cleans filenames and paths; use it like

这个类清除文件名和路径;喜欢使用它

var myCleanPath = PathSanitizer.SanitizeFilename(myBadPath, ' ');

Here's the code;

这里的代码;

/// <summary>
/// Cleans paths of invalid characters.
/// </summary>
public static class PathSanitizer
{
    /// <summary>
    /// The set of invalid filename characters, kept sorted for fast binary search
    /// </summary>
    private readonly static char[] invalidFilenameChars;
    /// <summary>
    /// The set of invalid path characters, kept sorted for fast binary search
    /// </summary>
    private readonly static char[] invalidPathChars;

    static PathSanitizer()
    {
        // set up the two arrays -- sorted once for speed.
        invalidFilenameChars = System.IO.Path.GetInvalidFileNameChars();
        invalidPathChars = System.IO.Path.GetInvalidPathChars();
        Array.Sort(invalidFilenameChars);
        Array.Sort(invalidPathChars);

    }

    /// <summary>
    /// Cleans a filename of invalid characters
    /// </summary>
    /// <param name="input">the string to clean</param>
    /// <param name="errorChar">the character which replaces bad characters</param>
    /// <returns></returns>
    public static string SanitizeFilename(string input, char errorChar)
    {
        return Sanitize(input, invalidFilenameChars, errorChar);
    }

    /// <summary>
    /// Cleans a path of invalid characters
    /// </summary>
    /// <param name="input">the string to clean</param>
    /// <param name="errorChar">the character which replaces bad characters</param>
    /// <returns></returns>
    public static string SanitizePath(string input, char errorChar)
    {
        return Sanitize(input, invalidPathChars, errorChar);
    }

    /// <summary>
    /// Cleans a string of invalid characters.
    /// </summary>
    /// <param name="input"></param>
    /// <param name="invalidChars"></param>
    /// <param name="errorChar"></param>
    /// <returns></returns>
    private static string Sanitize(string input, char[] invalidChars, char errorChar)
    {
        // null always sanitizes to null
        if (input == null) { return null; }
        StringBuilder result = new StringBuilder();
        foreach (var characterToTest in input)
        {
            // we binary search for the character in the invalid set. This should be lightning fast.
            if (Array.BinarySearch(invalidChars, characterToTest) >= 0)
            {
                // we found the character in the array of 
                result.Append(errorChar);
            }
            else
            {
                // the character was not found in invalid, so it is valid.
                result.Append(characterToTest);
            }
        }

        // we're done.
        return result.ToString();
    }

}

#6


21  

This is what I use:

这就是我使用的:

    public static bool IsValidFileName(this string expression, bool platformIndependent)
    {
        string sPattern = @"^(?!^(PRN|AUX|CLOCK\$|NUL|CON|COM\d|LPT\d|\..*)(\..+)?$)[^\x00-\x1f\\?*:\"";|/]+$";
        if (platformIndependent)
        {
           sPattern = @"^(([a-zA-Z]:|\\)\\)?(((\.)|(\.\.)|([^\\/:\*\?""\|<>\. ](([^\\/:\*\?""\|<>\. ])|([^\\/:\*\?""\|<>]*[^\\/:\*\?""\|<>\. ]))?))\\)*[^\\/:\*\?""\|<>\. ](([^\\/:\*\?""\|<>\. ])|([^\\/:\*\?""\|<>]*[^\\/:\*\?""\|<>\. ]))?$";
        }
        return (Regex.IsMatch(expression, sPattern, RegexOptions.CultureInvariant));
    }

The first pattern creates a regular expression containing the invalid/illegal file names and characters for Windows platforms only. The second one does the same but ensures that the name is legal for any platform.

第一个模式创建一个正则表达式,其中只包含Windows平台的无效/非法文件名和字符。第二种方法也是这样做的,但是要确保名称对任何平台都是合法的。

#7


17  

One corner case to keep in mind, which surprised me when I first found out about it: Windows allows leading space characters in file names! For example, the following are all legal, and distinct, file names on Windows (minus the quotes):

我第一次发现它的时候,我很惊讶:Windows允许文件名中的空格字符!例如,下列文件在Windows上都是合法的、不同的文件名(减去引号):

"file.txt"
" file.txt"
"  file.txt"

One takeaway from this: Use caution when writing code that trims leading/trailing whitespace from a filename string.

这里的一个要点是:在编写从filename字符串中引入/拖尾空格的代码时要小心。

#8


8  

Rather than explicitly include all possible characters, you could do a regex to check for the presence of illegal characters, and report an error then. Ideally your application should name the files exactly as the user wishes, and only cry foul if it stumbles across an error.

与其显式地包含所有可能的字符,不如使用regex检查是否存在非法字符,然后报告错误。理想情况下,应用程序应该按照用户的意愿来命名文件,只有在遇到错误时才会发出错误的叫声。

#9


7  

Microsoft Windows: Windows kernel forbids the use of characters in range 1-31 (i.e., 0x01-0x1F) and characters " * : < > ? \ |. Although NTFS allows each path component (directory or filename) to be 255 characters long and paths up to about 32767 characters long, the Windows kernel only supports paths up to 259 characters long. Additionally, Windows forbids the use of the MS-DOS device names AUX, CLOCK$, COM1, COM2, COM3, COM4, COM5, COM6, COM7, COM8, COM9, CON, LPT1, LPT2, LPT3, LPT4, LPT5, LPT6, LPT7, LPT8, LPT9, NUL and PRN, as well as these names with any extension (for example, AUX.txt), except when using Long UNC paths (ex. \.\C:\nul.txt or \?\D:\aux\con). (In fact, CLOCK$ may be used if an extension is provided.) These restrictions only apply to Windows - Linux, for example, allows use of " * : < > ? \ | even in NTFS.

Microsoft Windows: Windows内核禁止使用范围为1-31的字符。, 0x01-0x1F)和字符" *:< > ?\ |。虽然NTFS允许每个路径组件(目录或文件名)长度为255个字符,路径长度为32767个字符,但是Windows内核只支持长度为259个字符的路径。此外,Windows禁止使用ms - dos辅助设备名称,钟元,COM1、COM2、COM3 COM4为,COM5,COM6,COM7,COM8,COM9,案子,LPT1,LPT2,LPT3,LPT4,LPT5,LPT6,LPT7,LPT8,LPT9,NUL和打印,以及这些名称与任何扩展(例如,AUX.txt),除非使用长UNC路径(交货。\ \ C:\空。txt或者\ ? \ D:\辅助\ con)。(事实上,如果提供了扩展,则可以使用时钟$。)这些限制只适用于Windows - Linux,例如,允许使用“*:< > ?即使在NTFS中也可以使用|。

Source: http://en.wikipedia.org/wiki/Filename

来源:http://en.wikipedia.org/wiki/Filename

#10


6  

Also CON, PRN, AUX, NUL, COM# and a few others are never legal filenames in any directory with any extension.

还有CON, PRN, AUX, NUL, COM#和其他一些在任何扩展名的目录中都不是合法的文件名。

#11


6  

Simplifying the Eugene Katz's answer:

简化尤金·卡茨的回答:

bool IsFileNameCorrect(string fileName){
    return !fileName.Any(f=>Path.GetInvalidFileNameChars().Contains(f))
}

Or

bool IsFileNameCorrect(string fileName){
    return fileName.All(f=>!Path.GetInvalidFileNameChars().Contains(f))
}

#12


5  

The question is are you trying to determine if a path name is a legal windows path, or if it's legal on the system where the code is running.? I think the latter is more important, so personally, I'd probably decompose the full path and try to use _mkdir to create the directory the file belongs in, then try to create the file.

问题是,您是在尝试确定路径名是合法的windows路径,还是在代码运行的系统上,它是合法的?我认为后者更重要,所以就我个人而言,我可能会分解完整的路径并尝试使用_mkdir来创建文件所属的目录,然后尝试创建文件。

This way you know not only if the path contains only valid windows characters, but if it actually represents a path that can be written by this process.

这样,您不仅知道路径是否只包含有效的windows字符,而且如果它实际上表示一个可以由这个过程编写的路径。

#13


5  

I use this to get rid of invalid characters in filenames without throwing exceptions:

我使用这个来删除文件名中的无效字符,而不抛出异常:

private static readonly Regex InvalidFileRegex = new Regex(
    string.Format("[{0}]", Regex.Escape(@"<>:""/\|?*")));

public static string SanitizeFileName(string fileName)
{
    return InvalidFileRegex.Replace(fileName, string.Empty);
}

#14


4  

From MSDN, here's a list of characters that aren't allowed:

从MSDN,这里有一个不允许的字符列表:

Use almost any character in the current code page for a name, including Unicode characters and characters in the extended character set (128–255), except for the following:

在当前代码页中几乎任何字符都可用于名称,包括扩展字符集(128-255)中的Unicode字符和字符,但以下情况除外:

  • The following reserved characters are not allowed: < > : " / \ | ? *
  • 以下保留字符不允许:< >:" / \ | ?*
  • Characters whose integer representations are in the range from zero through 31 are not allowed.
  • 不允许字符的整数表示在0到31之间。
  • Any other character that the target file system does not allow.
  • 目标文件系统不允许的任何其他字符。

#15


3  

To complement the other answers, here are a couple of additional edge cases that you might want to consider.

为了补充其他的答案,这里有一些您可能需要考虑的附加边界情况。

  • Excel can have problems if you save a workbook in a file whose name contains the '[' or ']' characters. See http://support.microsoft.com/kb/215205 for details.

    如果您将工作簿保存在名称包含“['或']字符的文件中,Excel可能会出现问题。有关详细信息,请参阅http://support.microsoft.com/kb/215205。

  • Sharepoint has a whole additional set of restrictions. See http://support.microsoft.com/kb/905231 for details.

    Sharepoint有一整套附加的限制。有关详细信息,请参阅http://support.microsoft.com/kb/905231。

#16


2  

Also the destination file system is important.

目标文件系统也很重要。

Under NTFS, some files can not be created in specific directories. E.G. $Boot in root

在NTFS下,一些文件不能在特定的目录中创建。如引导美元的根

#17


2  

This is an already answered question, but just for the sake of "Other options", here's a non-ideal one:

这是一个已经回答过的问题,但为了“其他选择”,这里有一个非理想的选项:

(non-ideal because using Exceptions as flow control is a "Bad Thing", generally)

(不理想,因为使用异常作为流控制通常是一件“坏事”)

public static bool IsLegalFilename(string name)
{
    try 
    {
        var fileInfo = new FileInfo(name);
        return true;
    }
    catch
    {
        return false;
    }
}

#18


2  

Regular expressions are overkill for this situation. You can use the String.IndexOfAny() method in combination with Path.GetInvalidPathChars() and Path.GetInvalidFileNameChars().

对于这种情况,正则表达式是多余的。可以将String.IndexOfAny()方法与Path.GetInvalidPathChars()和Path.GetInvalidFileNameChars()结合使用。

Also note that both Path.GetInvalidXXX() methods clone an internal array and return the clone. So if you're going to be doing this a lot (thousands and thousands of times) you can cache a copy of the invalid chars array for reuse.

还要注意,Path.GetInvalidXXX()方法都克隆一个内部数组并返回克隆。如果你要做很多次(成千上万次)你可以缓存一个无效chars数组的副本以供重用。

#19


1  

Windows filenames are pretty unrestrictive, so really it might not even be that much of an issue. The characters that are disallowed by Windows are:

Windows文件名是非常没有限制的,所以它甚至可能不是那么大的问题。Windows不允许的字符是:

\ / : * ? " < > |

You could easily write an expression to check if those characters are present. A better solution though would be to try and name the files as the user wants, and alert them when a filename doesn't stick.

您可以轻松地编写一个表达式来检查这些字符是否存在。不过,更好的解决方案是尝试并按用户的要求命名文件,并在文件名不稳定时发出警告。

#20


1  

If you're only trying to check if a string holding your file name/path has any invalid characters, the fastest method I've found is to use Split() to break up the file name into an array of parts wherever there's an invalid character. If the result is only an array of 1, there are no invalid characters. :-)

如果您只是想检查保存文件名/路径的字符串是否有任何无效字符,那么我找到的最快的方法是使用Split()将文件名分解为一个部分数组,只要有无效字符。如果结果仅为1的数组,则没有无效字符。:-)

var nameToTest = "Best file name \"ever\".txt";
bool isInvalidName = nameToTest.Split(System.IO.Path.GetInvalidFileNameChars()).Length > 1;

var pathToTest = "C:\\My Folder <secrets>\\";
bool isInvalidPath = pathToTest.Split(System.IO.Path.GetInvalidPathChars()).Length > 1;

I tried running this and other methods mentioned above on a file/path name 1,000,000 times in LinqPad.

我在LinqPad中尝试在一个文件/路径名上运行这个和上面提到的其他方法1,000,000次。

Using Split() is only ~850ms.

使用Split()仅为~850ms。

Using Regex("[" + Regex.Escape(new string(System.IO.Path.GetInvalidPathChars())) + "]") is around 6 seconds.

使用正则表达式(“[”+正则表达式。Escape(新字符串System.IO.Path.GetInvalidPathChars()) +“]”)大约是6秒。

The more complicated regular expressions fair MUCH worse, as do some of the other options, like using the various methods on the Path class to get file name and let their internal validation do the job (most likely due to the overhead of exception handling).

更复杂的正则表达式会更糟,其他一些选项也是如此,比如使用Path类上的各种方法来获取文件名,并让它们的内部验证来完成这项工作(最可能的原因是异常处理的开销)。

Granted it's not very often you need to validation 1 million file names, so a single iteration is fine for most of these methods anyway. But it's still pretty efficient and effective if you're only looking for invalid characters.

当然,您通常不需要验证100万个文件名,因此,对于大多数这些方法来说,一次迭代都是可以的。但是如果你只寻找无效的字符,它仍然是非常有效的。

#21


1  

My attempt:

我的尝试:

using System.IO;

static class PathUtils
{
  public static string IsValidFullPath([NotNull] string fullPath)
  {
    if (string.IsNullOrWhiteSpace(fullPath))
      return "Path is null, empty or white space.";

    bool pathContainsInvalidChars = fullPath.IndexOfAny(Path.GetInvalidPathChars()) != -1;
    if (pathContainsInvalidChars)
      return "Path contains invalid characters.";

    string fileName = Path.GetFileName(fullPath);
    if (fileName == "")
      return "Path must contain a file name.";

    bool fileNameContainsInvalidChars = fileName.IndexOfAny(Path.GetInvalidFileNameChars()) != -1;
    if (fileNameContainsInvalidChars)
      return "File name contains invalid characters.";

    if (!Path.IsPathRooted(fullPath))
      return "The path must be absolute.";

    return "";
  }
}

This is not perfect because Path.GetInvalidPathChars does not return the complete set of characters that are invalid in file and directory names and of course there's plenty more subtleties.

这并不完美,因为路径。GetInvalidPathChars不会返回文件和目录名称中无效的完整字符集,当然还有更多的细节。

So I use this method as a complement:

所以我用这个方法作为补充:

public static bool TestIfFileCanBeCreated([NotNull] string fullPath)
{
  if (string.IsNullOrWhiteSpace(fullPath))
    throw new ArgumentException("Value cannot be null or whitespace.", "fullPath");

  string directoryName = Path.GetDirectoryName(fullPath);
  if (directoryName != null) Directory.CreateDirectory(directoryName);
  try
  {
    using (new FileStream(fullPath, FileMode.CreateNew)) { }
    File.Delete(fullPath);
    return true;
  }
  catch (IOException)
  {
    return false;
  }
}

It tries to create the file and return false if there is an exception. Of course, I need to create the file but I think it's the safest way to do that. Please also note that I am not deleting directories that have been created.

如果有异常,它尝试创建文件并返回false。当然,我需要创建文件,但我认为这是最安全的方式。请注意,我没有删除已创建的目录。

You can also use the first method to do basic validation, and then handle carefully the exceptions when the path is used.

您还可以使用第一个方法进行基本的验证,然后在使用路径时仔细地处理异常。

#22


0  

I suggest just use the Path.GetFullPath()

我建议使用Path.GetFullPath()

string tagetFileFullNameToBeChecked;
try
{
  Path.GetFullPath(tagetFileFullNameToBeChecked)
}
catch(AugumentException ex)
{
  // invalid chars found
}

#23


0  

many of these answers will not work if the filename is too long & running on a pre Windows 10 environment. Similarly, have a think about what you want to do with periods - allowing leading or trailing is technically valid, but can create problems if you do not want the file to be difficult to see or delete respectively.

如果文件名太长,并且在windows10前环境中运行,那么许多这些答案都不会起作用。类似地,考虑一下您想要对句点做什么——允许前导或尾随在技术上是有效的,但是如果您不希望文件分别难于查看或删除,则可能会产生问题。

This is a validation attribute I created to check for a valid filename.

这是我创建的用于检查有效文件名的验证属性。

public class ValidFileNameAttribute : ValidationAttribute
{
    public ValidFileNameAttribute()
    {
        RequireExtension = true;
        ErrorMessage = "{0} is an Invalid Filename";
        MaxLength = 255; //superseeded in modern windows environments
    }
    public override bool IsValid(object value)
    {
        //http://*.com/questions/422090/in-c-sharp-check-that-filename-is-possibly-valid-not-that-it-exists
        var fileName = (string)value;
        if (string.IsNullOrEmpty(fileName)) { return true;  }
        if (fileName.IndexOfAny(Path.GetInvalidFileNameChars()) > -1 ||
            (!AllowHidden && fileName[0] == '.') ||
            fileName[fileName.Length - 1]== '.' ||
            fileName.Length > MaxLength)
        {
            return false;
        }
        string extension = Path.GetExtension(fileName);
        return (!RequireExtension || extension != string.Empty)
            && (ExtensionList==null || ExtensionList.Contains(extension));
    }
    private const string _sepChar = ",";
    private IEnumerable<string> ExtensionList { get; set; }
    public bool AllowHidden { get; set; }
    public bool RequireExtension { get; set; }
    public int MaxLength { get; set; }
    public string AllowedExtensions {
        get { return string.Join(_sepChar, ExtensionList); } 
        set {
            if (string.IsNullOrEmpty(value))
            { ExtensionList = null; }
            else {
                ExtensionList = value.Split(new char[] { _sepChar[0] })
                    .Select(s => s[0] == '.' ? s : ('.' + s))
                    .ToList();
            }
    } }

    public override bool RequiresValidationContext => false;
}

and the tests

和测试

[TestMethod]
public void TestFilenameAttribute()
{
    var rxa = new ValidFileNameAttribute();
    Assert.IsFalse(rxa.IsValid("pptx."));
    Assert.IsFalse(rxa.IsValid("pp.tx."));
    Assert.IsFalse(rxa.IsValid("."));
    Assert.IsFalse(rxa.IsValid(".pp.tx"));
    Assert.IsFalse(rxa.IsValid(".pptx"));
    Assert.IsFalse(rxa.IsValid("pptx"));
    Assert.IsFalse(rxa.IsValid("a/abc.pptx"));
    Assert.IsFalse(rxa.IsValid("a\\abc.pptx"));
    Assert.IsFalse(rxa.IsValid("c:abc.pptx"));
    Assert.IsFalse(rxa.IsValid("c<abc.pptx"));
    Assert.IsTrue(rxa.IsValid("abc.pptx"));
    rxa = new ValidFileNameAttribute { AllowedExtensions = ".pptx" };
    Assert.IsFalse(rxa.IsValid("abc.docx"));
    Assert.IsTrue(rxa.IsValid("abc.pptx"));
}

#24


0  

I got this idea from someone. - don't know who. Let the OS do the heavy lifting.

我是从某人那里得到这个主意的。——不知道是谁。让操作系统来承担重任。

public bool IsPathFileNameGood(string fname)
{
    bool rc = Constants.Fail;
    try
    {
        this._stream = new StreamWriter(fname, true);
        rc = Constants.Pass;
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message, "Problem opening file");
        rc = Constants.Fail;
    }
    return rc;
}

#25


0  

This check

这张支票

static bool IsValidFileName(string name)
{
    return
        !string.IsNullOrWhiteSpace(name) &&
        name.IndexOfAny(Path.GetInvalidFileNameChars()) < 0 &&
        !Path.GetFullPath(name).StartsWith(@"\\.\");
}

filters out names with invalid chars (<>:"/\|?* and ASCII 0-31), as well as reserved DOS devices (CON, NUL, COMx). It allows leading spaces and all-dot-names, consistent with Path.GetFullPath. (Creating file with leading spaces succeeds on my system).

用无效字符过滤出名称(<>:"/\|?*和ASCII 0-31),以及保留的DOS设备(CON, NUL, COMx)。它允许前导空间和所有点名,与Path.GetFullPath一致。(在我的系统上创建具有领先空间的文件)。


Used .NET Framework 4.7.1, tested on Windows 7.

使用。net Framework 4.7.1,在Windows 7上测试。