从文件名(或目录、文件夹、文件)中移除无效(不允许、有问题的)字符。

23
我写了这个小方法来实现这个目标。但是有没有更高效(更简单)的方法?我希望这可以帮助像我一样搜索这个问题的人。
var fileName = new System.Text.StringBuilder();
fileName.Append("*Bad/\ :, Filename,? ");
// get rid of invalid chars
while (fileName.ToString().IndexOfAny(System.IO.Path.GetInvalidFileNameChars()) > -1)
{
    fileName = fileName.Remove(fileName.ToString().IndexOfAny(System.IO.Path.GetInvalidFileNameChars()), 1);
}

?

4个回答

122

我知道这已经过了几年,但是这里提供另一种参考解决方案。

public string GetSafeFilename(string filename)
{

    return string.Join("_", filename.Split(Path.GetInvalidFileNameChars()));

}

2
几年后,但是一个非常聪明的解决方案。截至2014年,仍然是我要使用的方法,而不是Regex.Replace。=D - Anderson Pimentel
没错,这是最好的解决方案。它还表明,阅读整个线程(并回答旧问题)是值得的。谢谢,Ceres。 - user1908746
2
@Rob GetInvalidFileNameChars() 包括 '' 和 '/'。此例程假定您只传递文件名。如果您要检查文件路径的一部分,则可以使用 Path.GetInvalidPathChars() - Ceres
文件夹名称也适用吗? - Kiquenet
@Kiquenet GetInvalidPathChars() 用于文件夹,GetInvalidFileNameChars() 用于文件名。 - Ceres
Path.InvalidPathChars 不包括通配符字符 *、?,以及冒号、反斜杠、正斜杠、小于号和大于号,还有双引号。 - Kiquenet

17

尝试以下内容

public string MakeValidFileName(string name) {
  var builder = new StringBuilder();
  var invalid = System.IO.Path.GetInvalidFileNameChars();
  foreach ( var cur in name ) {
    if ( !invalid.Contains(cur) ) {
      builder.Append(cur);
    }
  }
  return builder.ToString();
}

2
在.NET 4中,invalid.Contains(cur)似乎对我无效。出现了“无法在此处访问私有方法”的消息。下面发布了另一个示例。 - Roland Schaer
在顶部添加 using System.Linq。 - user565710

14

一种与.NET 4兼容的不同方法。请参阅我上面解释需求的评论。

public static string ScrubFileName(string value)
{
   var sb = new StringBuilder(value);
   foreach (char item in Path.GetInvalidFileNameChars())
   {
      sb.Replace(item.ToString(), "");
   }
   return sb.ToString();
}

不使用 StringBuilder: -1 - John Saunders

-1

如果你说“简单”时想要表达“简洁”:

public string StripInvalidChars(string filename) {
  return new String(
    filename.Except(System.IO.Path.GetInvalidFileNameChars()).ToArray()
  );
}

说实话,我会选择JaredPar的解决方案。它可能更容易阅读(取决于口味和背景),我的直觉是它更有效率(尽管我不确定从有限长度的文件名中剥离那些无效字符需要多么高效),而他使用StringBuilder()似乎完美地适合你的例子。

3
我不相信"Except"方法能够满足你的需求。它不能很好地处理重复项。根据文档描述,该方法返回第一个列表中与第二个列表不同的元素,并不会返回第二个列表中与第一个列表不同的元素。该描述来自于http://msdn.microsoft.com/en-us/library/bb300779.aspx。 - ChronoPositron
@ChronoPositron:启示我:问题是什么? 我想要“第一个中出现但不在第二个中出现的元素”(即不是无效字符的字符)。我不想要“第二个中出现但不在第一个中出现的元素”(即不出现的无效字符)。 - Benjamin Podszun
问题在于Except函数作为一个集合操作。例如,如果我将“aaabbb.txt”(这是一个有效的文件名)传递给您的函数,则结果值为“ab.tx”。它只保留每个字母的第一次出现,这使得它删除了比无效字符更多的内容;它改变了函数的预期结果。 - ChronoPositron
1
@ChronoPositron:哇,你抓住我了。我之前漏掉了“set”部分,当我在LINQPad中快速测试OP的测试数据时,我只注意到了已删除的无效字符(好的),而没有注意到缺失的有效元素(不好)。对于我的迟钝,我感到抱歉,谢谢你启发我。 - Benjamin Podszun
你能否编辑你的帖子并添加一个警告? - Bernhard

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接