【问题标题】:Easiest way to check if an arbitrary String is a valid filename检查任意字符串是否为有效文件名的最简单方法
【发布时间】:2011-01-10 19:07:17
【问题描述】:

在我的应用程序中,用户可以输入文件名。在处理之前,我想检查输入字符串是否是 Windows Vista 上的有效文件名。

最简单的方法是什么?

有效我指的是合法且不存在的

【问题讨论】:

  • 当您说有效的文件名时,您是指文件存在这一事实,还是您在询问操作系统是否允许该名称?
  • 在 (a) 现有、(b) 合法或 (c) 合法且不存在的情况下是否有效?
  • 对不起,我应该澄清一下。它应该是 (c) 合法且不存在的
  • @roflcopter:您必须在创建文件时简单地处理错误。任何涉及存在性检查的文件系统操作在返回时都可能已过期,因为文件系统是全局共享资源。
  • @Roflcoptr:在您检查有效性和/或存在的那一刻与您实际尝试创建它的那一刻之间创建的具有完全相同名称的文件不应被视为正常的程序流程。您应该验证该文件不存在,但当您实际创建该文件时,该知识已经过时,应仅被视为有根据的猜测。它可能仍然是正确的,但它不是保证

标签: c# .net file


【解决方案1】:

检查是否有filename.IndexOfAny(Path.GetInvalidFileNameChars()) < 0!File.Exists(Path.Combine(someFolder, filename))

【讨论】:

  • 不保证从此方法返回的数组包含文件和目录名称中无效的完整字符集。此外,该属性已被弃用。
  • 反例:"http://www.microsoft.com/" 通过了您的测试,但不是有效的文件名,"::::" 同上
  • 更多反例:" " 无效,new String('x', 1024) 也无效。
  • @shellster 您可以在 Windows 资源管理器中将文件重命名为“.txt”,方法是告诉资源管理器将文件重命名为“.txt”。只是一个提示(或“.txt........”也可以)。
  • 应该是 < 0 而不是 >= 0,因为如果找不到,IndexOfAny() 将返回 -1
【解决方案2】:

检查GetInvalidFileNameChars()

var isValid = !string.IsNullOrEmpty(fileName) &&
              fileName.IndexOfAny(Path.GetInvalidFileNameChars()) < 0 &&
              !File.Exists(Path.Combine(sourceFolder, fileName));

【讨论】:

  • 反例:"http://www.microsoft.com/" 通过了您的测试,但不是有效的文件名,"::::" 同上
  • @Ben Voigt:您是正确的,:::: 被错误地视为有效。我已将答案更正为 &lt; 0 而不是 == 0
  • 哦,我刚刚注意到您使用的是 GetInvalidFileNameChars,而不是像 SLaks 那样的 GetInvalidPathChars。只要它只是对文件名而不是文件名与路径的测试,就可以了。
  • @Ben Voigt:由于 OP 询问有关验证文件名的问题,并且路径仅隐含地验证文件不存在,因此我使用了 GetInvalidFileNameChars :-)
【解决方案3】:

如果要创建文件,您应该使用文件对话框来指定目录路径。有一个文件名非法字符的简短列表。

判断文件名是否可接受的唯一真正可靠的方法是尝试它。权限 是个烂摊子。

【讨论】:

  • 文件对话框是一个红鲱鱼,但 +1 表示“只有真正可靠的方法......是尝试它”。
  • 同意。即使文件名不存在且不包含非法字符,文件无法创建的原因也有很多,最明显的原因是缺少目录的创建权限。
  • 有些情况需要保存到未知路径,但又不希望用户选择准确的路径。在这些情况下,文件对话框是不可行的。
【解决方案4】:

我用这个:

public static bool IsValidFileName(string name) {
    if(string.IsNullOrWhiteSpace(name)) return false;
    if(name.Length > 1 && name[1] == ':') {
        if(name.Length < 4 || name.ToLower()[0] < 'a' || name.ToLower()[0] > 'z' || name[2] != '\\') return false;
        name = name.Substring(3);
    }
    if(name.StartsWith("\\\\")) name = name.Substring(1);
    if(name.EndsWith("\\") || !name.Trim().Equals(name) || name.Contains("\\\\") ||
        name.IndexOfAny(Path.GetInvalidFileNameChars().Where(x=>x!='\\').ToArray()) >= 0) return false;
    return true;
}

除了保留名称、权限和长度限制外,应该处理所有事情。这接受相对和绝对文件名。

【讨论】:

    【解决方案5】:

    这只是一个想法。应该填写例外列表:

    public static bool IsValidFilename(string filename)
    {
        try
        {
            File.OpenRead(filename).Close();
        }
        catch (ArgumentException) { return false; }
        catch (Exception) { }
        return true;
    }
    

    【讨论】:

    • 如果文件还不存在怎么办?
    • @MikeCheel 该代码仅在引发参数异常时才返回 false。只有文件名无效才会抛出该异常。
    【解决方案6】:

    对于第一部分(有效文件名),我使用所有方法和临时文件创建来检查文件是否可以按预期命名或引发异常。
    在某些情况下,创建文件在尝试删除文件之前不会引发异常(例如:CON)。
    我还使用removePath arg 来指示文件只是没有路径的文件名。

    using System.IO;
    using System.Text;
    
    private static readonly byte[] TestFileBytes = Encoding.ASCII.GetBytes(@"X");
    
    public bool IsFileNameValid(string file, bool removePath = false)
    {
        try
        {
            if (string.IsNullOrEmpty(file))
                return false;
    
            string fileNamePart = removePath ? Path.GetFileName(file) : file;
            if (fileNamePart.IndexOfAny(Path.GetInvalidFileNameChars()) >= 0)
                return false;
    
            string fileName = Path.Combine(Path.GetTempPath(), fileNamePart);
            using FileStream fileStream = File.Create(fileName);
            {
                fileStream.Write(TestFileBytes, 0, TestFileBytes.Length);
            }
    
            File.Delete(fileName);
            return true;
        }
        catch
        {
            return false;
        }
    }
    

    如果拒绝访问临时文件夹,请使用自定义文件夹来创建测试文件。

    此方法将导致false 用于...... r Windows 中的任何纯点名称序列,您也无法手动创建它们,但这些实际上不是无效名称!这些是无法创建的文件名称或类似名称;)。

    对于下一部分(不存在),只需使用:!File.Exists(yourFileNameWithPath)

    【讨论】:

      猜你喜欢
      • 2012-07-13
      • 2011-12-28
      • 2017-03-29
      • 2012-08-28
      • 2012-09-03
      • 2020-01-19
      • 2011-12-19
      • 1970-01-01
      • 2012-12-21
      相关资源
      最近更新 更多