如何从路径和文件名中删除非法字符?

时间:2020-03-06 14:50:50  来源:igfitidea点击:

我需要一种健壮且简单的方法来从简单的字符串中删除非法的路径和文件字符。我使用了下面的代码,但是它似乎什么也没做,我想念的是什么?

using System;
using System.IO;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            string illegal = "\"M<>\"\a/ry/ h**ad:>> a\/:*?\"<>| li*tt|le|| la\"mb.?";

            illegal = illegal.Trim(Path.GetInvalidFileNameChars());
            illegal = illegal.Trim(Path.GetInvalidPathChars());

            Console.WriteLine(illegal);
            Console.ReadLine();
        }
    }
}

解决方案

对于初学者,Trim仅从字符串的开头或者结尾删除字符。其次,我们应该评估我们是否真的要删除令人反感的字符,或者快速失败并让用户知道其文件名无效。我的选择是后者,但我的答案至少应该向我们展示如何以正确和错误的方式做事:

显示如何检查给定字符串是否为有效文件名的StackOverflow问题。请注意,我们可以使用此问题中的正则表达式删除带有正则表达式替换的字符(如果确实需要这样做)。

尝试这样的事情;

string illegal = "\"M\"\a/ry/ h**ad:>> a\/:*?\"| li*tt|le|| la\"mb.?";
string invalid = new string(Path.GetInvalidFileNameChars()) + new string(Path.GetInvalidPathChars());

foreach (char c in invalid)
{
    illegal = illegal.Replace(c.ToString(), ""); 
}

但是我必须同意这些意见,我可能会尝试处理非法路径的来源,而不是试图将非法路径变为合法但可能是意想不到的路径。

编辑:或者使用Regex的解决方案,可能是一个"更好"的解决方案。

string illegal = "\"M\"\a/ry/ h**ad:>> a\/:*?\"| li*tt|le|| la\"mb.?";
string regexSearch = new string(Path.GetInvalidFileNameChars()) + new string(Path.GetInvalidPathChars());
Regex r = new Regex(string.Format("[{0}]", Regex.Escape(regexSearch)));
illegal = r.Replace(illegal, "");

仍然有个问题要问,为什么首先要这样做。

我认为使用正则表达式进行验证并指定允许使用哪些字符要容易得多,而不是尝试检查所有不良字符。
请参阅以下链接:
http://www.c-sharpcorner.com/UploadFile/prasad_1/RegExpPSD12062005021717AM/RegExpPSD.aspx
http://www.windowsdevcenter.com/pub/a/oreilly/windows/news/csharp_0101.html

另外,搜索"正则表达式编辑器"也很有帮助。有一些甚至可以在cfor中输出代码。

我使用正则表达式来实现这一目标。首先,我动态构建正则表达式。

string regex = string.Format(
                   "[{0}]",
                   Regex.Escape(new string(Path.GetInvalidFileNameChars())));
Regex removeInvalidChars = new Regex(regex, RegexOptions.Singleline | RegexOptions.Compiled | RegexOptions.CultureInvariant);

然后,我只是调用removeInvalidChars.Replace进行查找和替换。显然,这也可以扩展为覆盖路径字符。

引发异常。

if ( fileName.IndexOfAny(Path.GetInvalidFileNameChars()) > -1 )
            {
                throw new ArgumentException();
            }

这是一个对.NET 3及更高版本有所帮助的代码段。

using System.IO;
using System.Text.RegularExpressions;

public static class PathValidation
{
    private static string pathValidatorExpression = "^[^" + string.Join("", Array.ConvertAll(Path.GetInvalidPathChars(), x => Regex.Escape(x.ToString()))) + "]+$";
    private static Regex pathValidator = new Regex(pathValidatorExpression, RegexOptions.Compiled);

    private static string fileNameValidatorExpression = "^[^" + string.Join("", Array.ConvertAll(Path.GetInvalidFileNameChars(), x => Regex.Escape(x.ToString()))) + "]+$";
    private static Regex fileNameValidator = new Regex(fileNameValidatorExpression, RegexOptions.Compiled);

    private static string pathCleanerExpression = "[" + string.Join("", Array.ConvertAll(Path.GetInvalidPathChars(), x => Regex.Escape(x.ToString()))) + "]";
    private static Regex pathCleaner = new Regex(pathCleanerExpression, RegexOptions.Compiled);

    private static string fileNameCleanerExpression = "[" + string.Join("", Array.ConvertAll(Path.GetInvalidFileNameChars(), x => Regex.Escape(x.ToString()))) + "]";
    private static Regex fileNameCleaner = new Regex(fileNameCleanerExpression, RegexOptions.Compiled);

    public static bool ValidatePath(string path)
    {
        return pathValidator.IsMatch(path);
    }

    public static bool ValidateFileName(string fileName)
    {
        return fileNameValidator.IsMatch(fileName);
    }

    public static string CleanPath(string path)
    {
        return pathCleaner.Replace(path, "");
    }

    public static string CleanFileName(string fileName)
    {
        return fileNameCleaner.Replace(fileName, "");
    }
}

我们可以使用Linq删除非法字符,如下所示:

var invalidChars = Path.GetInvalidFileNameChars();

var invalidCharsRemoved = stringWithInvalidChars
.Where(x => !invalidChars.Contains(x))
.ToArray();

编辑
注释中提到的必需编辑是这样的:

var invalidChars = Path.GetInvalidFileNameChars();

string invalidCharsRemoved = new string(stringWithInvalidChars
  .Where(x => !invalidChars.Contains(x))
  .ToArray());