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


165

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


我建议使用正则表达式编译如果你打算使用任何与正则表达式的答案静态..
AMissico

Answers:


100

您可以从Path.GetInvalidPathChars和获取无效字符列表GetInvalidFileNameChars

UPD:有关如何在正则表达式中使用它们的信息,请参阅Steve Cooper的建议

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


11
这不能回答问题。有许多仅由有效字符组成的字符串(例如,“ ....”,“ CON”,长度为数百个字符的字符串)不是有效的文件名。
Dour High Arch

31
其他人感到失望的是,MS没有为此功能提供系统级功能/ API,而是每个开发人员都必须自己准备解决方案?想知道这是一个很好的原因还是对MS部分的疏忽。
Thomas Nguyen

@High Arch:请参见问题“在C#中检查文件名可能有效(不存在)”的答案。(尽管有些聪明的人赞成这个问题,但还是解决了这个问题。)
mmmmmmmm 2015年

129

MSDN的“命名文件或目录”中,以下是Windows下合法文件名的常规约定:

您可以在当前代码页中使用任何字符(Unicode / ANSI高于127),但以下情况除外:

  • < > : " / \ | ? *
  • 整数表示形式为0-31(小于ASCII空间)的字符
  • 目标文件系统不允许的任何其他字符(例如,结尾的句点或空格)
  • 任意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(并避免使用AUX.txt等)
  • 文件名是所有句点

一些可选的检查事项:

  • 文件路径(包括文件名)不得超过260个字符(不使用\?\前缀)
  • 使用时具有超过32,000个字符的Unicode文件路径(包括文件名)\?\(请注意,前缀可能会扩展目录组件,并导致其超出32,000个限制)

8
+1(包括保留的文件名)-先前答案中未包含的文件名。
SqlRyan

2
如果使用“ \\?\”语法,则“ AUX”是一个完全可用的文件名。当然,不使用该语法的程序在处理它时会遇到真正的问题...(在XP上测试)
user9876 2009年

9
上面提到的所有这些条件的正确正则表达式如下:Regex unspupportedRegex = new Regex("(^(PRN|AUX|NUL|CON|COM[1-9]|LPT[1-9]|(\\.+)$)(\\..*)?$)|(([\\x00-\\x1f\\\\?*:\";|/<>])+)|(([\\. ]+)", RegexOptions.IgnoreCase);
为什么为什么2015年

4
@whywhywhy为什么我认为您在该Regex中有一个额外的开头括号。“((^(PRN | AUX | NUL | CON | COM [1-9] | LPT [1-9] |(\\。+)$)(\\ .. *)?$)|(([ X00 - \\ X1F \\\\ *:\ “; | / <>])+)|([\\] +)。”为我工作?
Wilky

4
我阅读了此答案中提到的同一篇文章,并通过实验发现也不允许使用COM0和LPT0。@dlf这一项适用于以“。”开头的文件名:^(?!^(?:PRN|AUX|CLOCK\$|NUL|CON|COM\d|LPT\d)(?:\..+)?$)(?:\.*?(?!\.))[^\x00-\x1f\\?*:\";|\/<>]+(?<![\s.])$
mjohnsonengr

67

对于3.5之前的.Net Frameworks,它应该可以工作:

正则表达式匹配应该为您提供一些帮助。这是使用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;
}

对于3.0之后的.Net Frameworks,它应该可以工作:

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

正则表达式匹配应该为您提供一些帮助。这是使用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;
}

知道之后,您还应该检查其他格式,例如c:\my\drive\\server\share\dir\file.ext


这不只是测试路径,而不是文件名吗?
尤金·卡兹

30
字符串strTheseAreInvalidFileNameChars =新字符串(System.IO.Path.GetInvalidFileNameChars()); 正则表达式regFixFileName =新Regex(“ [” + Regex.Escape(strTheseAreInvalidFileNameChars)+“]”);

2
人们的一点研究就能创造奇迹。我更新了帖子以反映所做的更改。
Erik Philips

1
第二段代码无法编译。“无法从char []转换为字符串
Paul Hunt 2014年

1
@AshkanMobayenKhiabani:InvalidPathChars已过时,但GetInvalidPathChars没有。
伊凡

25

尝试使用它,并捕获错误。允许的集合可能会在文件系统或Windows的不同版本中发生变化。换句话说,如果您想知道Windows是否喜欢该名称,请将该名称递给您,然后告诉您。


1
这似乎是唯一可以克服所有限制的测试方法。为什么要选择其他答案呢?
缺口

5
@gap,因为它并不总是有效。例如,即使不是真正的文件,尝试访问CON也会成功。
锑2012年

4
不过,最好尽可能避免引发异常的内存开销。
欧文·布莱克

2
另外,您可能没有访问权限。例如通过编写来测试它,即使您可以阅读它是否存在或将存在。
CodeLurker

23

此类清除文件名和路径;像这样使用

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

这是代码;

/// <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();
    }

}

1
你的答案可以更好地适应这里:stackoverflow.com/questions/146134/...
nawfal

22

这是我用的:

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

第一个模式创建一个正则表达式,仅包含Windows平台的无效/非法文件名和字符。第二个功能相同,但是确保名称对任何平台都是合法的。


4
sPattern正则表达式不允许以句点字符开头的文件。但是MSDN说: “可以将句点指定为名称的首字符。例如,“。temp”。我将删除“ \ .. *”以使.gitignore成为正确的文件名:)
yar_shukan 2014年

(我已经逐步改进了它,并删除了我留下的上一条注释)这比答案的正则表达式更好,因为它允许“ .gitignore”,“ .. asdf”,不允许“ <”和“>”或日元符号,并且末尾不允许有空格或句点(不允许名称仅由点组成):@"^(?!(?:PRN|AUX|CLOCK\$|NUL|CON|COM\d|LPT\d)(?:\..+)?$)[^\x00-\x1F\xA5\\?*:\"";|\/<>]+(?<![\s.])$"
mjohnsonengr

这对于我测试的所有文件均失败。为C:\ Windows \ System32 \ msxml6.dll运行它报告为false。
magicandre1981 '16

@ magicandre1981您只需要给它一个文件名,而不是完全限定的路径。
Scott Dorman

好的,但是我需要检查完整路径是否有效。我现在使用了不同的解决方案。
magicandre1981 '16

18

要牢记一个极端的情况,当我第一次发现它时,这让我感到惊讶:Windows允许在文件名中使用前导空格字符!例如,以下是Windows上所有合法且不同的文件名(减去引号):

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

这样做的一个好处:编写代码以修剪文件名字符串中的前导/尾随空格时要格外小心。


10

简化Eugene Katz的答案:

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

要么

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

您的意思是:“返回!fileName.Any(f => Path.GetInvalidFileNameChars()。Contains(f));” ?
杰克格里芬

@JackGriffin当然!感谢您的关注。
tmt

尽管这段代码非常好看,但我们应该考虑到令人遗憾的内部原理Path.GetInvalidFileNameChars。在这里看看:referencesource.microsoft.com/#mscorlib/system/io/path.cs,289-为您的每个字符fileName创建一个数组的克隆。
Piotr Zierhoffer

“ DD:\\\\\ AAA ..... AAAA”。无效,但对您的代码而言是有效的。
Ciccio Pasticcio

8

Microsoft Windows:Windows内核禁止使用范围为1-31的字符(即0x01-0x1F)和字符“ *:<>?\ |。尽管NTFS允许每个路径组件(目录或文件名)的长度为255个字符,并且Windows内核最多支持32767个字符的路径,Windows内核仅支持长达259个字符的路径。此外,Windows禁止使用MS-DOS设备名称AUX,CLOCK $,COM1,COM2,COM3,COM4,COM5,COM6, COM7,COM8,COM9,CON,LPT1,LPT2,LPT3,LPT4,LPT5,LPT6,LPT7,LPT8,LPT9,NUL和PRN以及带有任何扩展名的这些名称(例如AUX.txt),除非使用长UNC路径(例如\。\ C:\ nul.txt或\?\ D:\ aux \ con)(实际上,如果提供了扩展名,则可以使用CLOCK $。)这些限制仅适用于Windows-例如,Linux允许使用“ *:<>?\ | 即使在NTFS中。

资料来源:http : //en.wikipedia.org/wiki/文件名


1
我可以创建一个名为“ CLOCK $”的文件。Windows7。–
rory.ap

7

您可以执行正则表达式来检查是否存在非法字符,而不是显式包括所有可能的字符,然后报告错误。理想情况下,您的应用程序应完全按照用户希望的方式命名文件,并且仅当偶然发现错误时才叫犯规。


6

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

这样,您不仅知道路径是否仅包含有效的Windows字符,而且还知道它是否实际代表可以由该过程写入的路径。


6

我用它来摆脱文件名中的无效字符而不会引发异常:

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

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

5

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


1
这只是事实的一半。如果调用Unicode版本的CreateFile(使用“ \\?\”前缀文件名),则可以使用这些名称创建文件。
Werner Henze

该声明不完整,缺少LPT#
Thomas Weller '18


3

MSDN中,这是不允许的字符列表:

当前代码页中的几乎所有字符都用作名称,包括Unicode字符和扩展字符集(128–255)中的字符,但以下各项除外:

  • 不允许使用以下保留字符:<>:“ / / |?*
  • 不允许使用整数表示形式,范围从零到31的字符。
  • 目标文件系统不允许的任何其他字符。

2

目标文件系统也很重要。

在NTFS下,无法在特定目录中创建某些文件。EG $根启动


2
当然,这不是由于NTFS命名规则,而仅仅是因为$Boot目录中已经存在一个名为的文件吗?
克里斯蒂安·海特

2

这是一个已经回答的问题,但是仅出于“其他选择”的考虑,这是一个不理想的问题:

(不理想,因为使用异常作为流控制通常是“错误的事情”)

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

您的示例不适用于CON文件(C:\ temp \ CON)。
tcbrazil 2015年

但是'C:\ temp \ CON'不是有效的文件名吗?为什么不呢?
马克·A·多诺霍

@MarqueIV-不,它无效。阅读以上所有答案和评论,或者自己尝试看看。
rory.ap

@Jer,“ / example”不合法,但您的方法返回true
rory.ap

aa ...我错过了'CON'部分。从字符串的角度来看,该名称本身是有效的(这就是我所指的意思),但是现在我看到CON是保留名称,从Windows的角度来看,它是无效的。我的错。
Mark A. Donohoe

2

对于这种情况,正则表达式会显得过分杀伤力。您可以将String.IndexOfAny()方法与Path.GetInvalidPathChars()和结合使用Path.GetInvalidFileNameChars()

还要注意,这两种Path.GetInvalidXXX()方法都将克隆内部数组并返回克隆。因此,如果您要进行很多次(成千上万次),则可以缓存无效chars数组的副本以供重复使用。


2

如果您只是想检查包含文件名/路径的字符串中是否有任何无效字符,那么我发现的最快方法是使用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;

我尝试在LinqPad中对文件/路径名称运行1,000,000次,并运行了上面提到的其他方法。

使用Split()仅约850ms。

使用Regex("[" + Regex.Escape(new string(System.IO.Path.GetInvalidPathChars())) + "]")大约需要6秒钟。

与其他一些选项一样,更复杂的正则表达式更糟,例如,使用Path类上的各种方法来获取文件名并让其内部验证完成任务(很可能是由于异常处理的开销)。

当然,您很少需要验证一百万个文件名,因此对于大多数这些方法而言,一次迭代都可以。但是,如果您只查找无效字符,它仍然非常有效。


1

如果文件名太长且在Windows 10之前的环境中运行,这些答案中的许多将不起作用。同样,请考虑一下您要对句点进行的操作-允许前导或尾随在技术上是有效的,但是如果您不希望分别难以查看或删除文件,则会造成问题。

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

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://stackoverflow.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;
}

和测试

[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"));
}

1

我的尝试:

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

这是不完美的,因为Path.GetInvalidPathChars不会返回文件和目录名称中无效的完整字符集,当然还有很多细微之处。

因此,我使用此方法作为补充:

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

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

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


0

我建议只使用Path.GetFullPath()

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

与答案添加一些解释如何回答帮助OP在固定电流问题
ρяσѕρєяķ

请参阅MSDN中的AugumentExcpetion文档,其内容为:path是长度为零的字符串,仅包含空格,或包含GetInvalidPathChars中定义的一个或多个无效字符。-或者-系统无法检索绝对路径。
东尼·孙

从理论上讲(根据文档),这应该可以工作,但问题至少是在.NET Core 3.1中却没有。
Michel Jansson

0

我是从某人那里得到这个想法的。-不知道是谁 让OS承担繁重的工作。

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

0

这张支票

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

过滤掉无效字符(名称<>:"/\|?*和ASCII 0-31),以及保留DOS设备(CONNULCOMx)。它允许前导空格和全点名,与一致Path.GetFullPath。(在系统上成功创建带有前导空格的文件)。


使用.NET Framework 4.7.1,已在Windows 7上进行了测试。


0

一种用于验证字符串中非法字符的衬里:

public static bool IsValidFilename(string testName) => !Regex.IsMatch(testName, "[" + Regex.Escape(new string(System.IO.Path.InvalidPathChars)) + "]");

0

我认为,对此问题的唯一正确答案是尝试使用路径,并让OS和文件系统对其进行验证。否则,您将只是重新实现(并且可能效果很差)操作系统和文件系统已经使用的所有验证规则,并且如果将来更改了这些规则,则必须更改代码以使其匹配。


-1

Windows文件名是没有限制的,因此实际上它甚至不是什么大问题。Windows禁止使用的字符是:

\ / : * ? " < > |

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


此外,字符<= 31也被禁止。
锑2012年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.