当前位置:  开发笔记 > 编程语言 > 正文

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

如何解决《如何从路径和文件名中删除非法字符?》经验,为你挑选了14个好方法。

我需要一种强大而简单的方法来从简单的字符串中删除非法路径和文件字符.我使用了下面的代码,但它似乎没有做任何事情,我错过了什么?

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

Matthew Scha.. 473

尝试这样的事情;

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

但我不得不同意这些评论,我可能会尝试处理非法路径的来源,而不是试图将非法路径变成合法但可能是非预期路径.

编辑:或使用正则表达式的潜在"更好"的解决方案.

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, "");

不过,问题还有待提出,为什么你首先要这样做.



1> Matthew Scha..:

尝试这样的事情;

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

但我不得不同意这些评论,我可能会尝试处理非法路径的来源,而不是试图将非法路径变成合法但可能是非预期路径.

编辑:或使用正则表达式的潜在"更好"的解决方案.

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, "");

不过,问题还有待提出,为什么你首先要这样做.


没有必要将两个列表附加在一起.非法文件名字符列表包含非法路径字符列表,还有一些.以下是转换为int的两个列表的列表:34,60,62,124,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16, 17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,58,42,63,92,47 34,60,62,124,0,1,2 ,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27 ,28,29,30,31
@Charleh这个讨论是如此不必要......代码应该始终优化,并且不存在不正确的风险.文件名也是路径的一部分.因此,`GetInvalidPathChars()`可能包含`GetInvalidFileNameChars()`不会出现的字符,这是不合逻辑的.你没有对"过早"的优化采取正确的态度.你只是使用不好的代码.
@sjbotha这可能适用于Windows和Microsoft的.NET实现我不愿意为单声道运行Linux做同样的假设.
关于第一个解决方案.StringBuilder不应该比字符串赋值更有效吗?
值得称道的是@MatthewScharley,GetInvalidPathChars()的Mono实现仅返回0x00,而GetInvalidFileNameChars()在非Windows平台上运行时仅返回0x00和'/'.在Windows上,无效字符列表要长得多,并且GetInvalidPathChars()在GetInvalidFileNameChars()中完全重复.这在可预见的未来不会发生变化,所以你真正做的就是将这个函数运行的时间加倍,因为你担心有效路径的定义会很快改变.它不会.
@Warren:如果你真的很担心的话,可以随意重复演绎得到的字符串,但我们在这里说得非常诚实:对于字符串的20到40次迭代与平均路径的长度之间的差异(假设100个字符是慷慨的)将会使与函数的运行时完全相同*没有*差异.对于所有*实用*目的,没有必要担心它.另一方面,这两个函数确实用于不同的目的(至少在我看来),对于某个给定的文件系统,一个函数不返回另一个函数的超集是完全合理的.
什么是消毒问题,Bob Tables?
GetInvalidFileNameChars()总是 - 总是,你听到我 - 将包含在GetInvalidPathChars()中的所有内容,因为文件中的某个字符无法在路径名中无效.今天没有文件系统允许这样,没有文件系统.无论如何,微软自己的这些函数文档非常清楚地表明你不应该期望字符列表保证准确,因为文件系统可能支持不同的东西.
我可能会在这里与马修站在一起,只是说假设是所有混乱的母亲.您正在谈论优化代码,这些代码可能不需要针对潜在的正确性进行优化.我会在任何一天对过早优化采取正确的态度
@JoeyAdams:看到我对Sarel Botha的回复.简而言之,一个是Windows上另一个的超集.就个人而言,我不愿意在跨平台上做同样的赌注,而C#和.NET一般都是通过Mono获得更广泛的观众.

2> Shehab Fawzy..:
public string RemoveInvalidChars(string filename)
{
    return string.Concat(filename.Split(Path.GetInvalidFileNameChars()));
}

这个答案是Ceres的另一个主题,我真的很喜欢它简洁明了.


我测试了这个问题的五种方法(定时循环为100,000),这种方法是最快的.正则表达式排在第2位,比此方法慢25%.
要准确回答OP的问题,你需要使用""代替"_",但你的答案可能适用于我们在实践中的更多人.我认为用一些合法的字符替换非法字符更常见.
要解决@BH的注释,可以简单地使用string.Concat(name.Split(Path.GetInvalidFileNameChars()))

3> Michael Mint..:

我使用Linq来清理文件名.您可以轻松扩展它以检查有效路径.

private static string CleanFileName(string fileName)
{
    return Path.GetInvalidFileNameChars().Aggregate(fileName, (current, c) => current.Replace(c.ToString(), string.Empty));
}

更新

一些评论表明这种方法对他们不起作用所以我已经包含了一个指向DotNetFiddle代码段的链接,因此您可以验证该方法.

https://dotnetfiddle.net/nw1SWY


这不适合我.该方法不返回干净的字符串.它按原样返回传递的文件名.
这很容易 - 人们正在传递有效字符串.赞成酷聚合解决方案.
@Karan或Jon您发送此功能的输入是什么?请参阅我的编辑以验证此方法.

4> Gregor Slave..:

您可以使用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());


我知道这是一个老问题,但这是一个很棒的答案.但是,我想在c#中添加你无法隐式或显式地从char []转换为字符串(疯狂,我知道)所以你需要将它放入字符串构造函数中.
@anjdreas实际上Path.GetInvalidPathChars()似乎是Path.GetInvalidFileNameChars()的子集,而不是相反的方式.例如,Path.GetInvalidPathChars()不会返回'?'.

5> René..:

这些都是很好的解决方案,但它们都依赖于Path.GetInvalidFileNameChars,这可能不像你想象的那么可靠.请注意MSDN文档中的以下注释Path.GetInvalidFileNameChars:

从此方法返回的数组不保证包含在文件和目录名称中无效的完整字符集.完整的无效字符集可能因文件系统而异.例如,在基于Windows的桌面平台上,无效路径字符可能包括ASCII/Unicode字符1到31,以及quote("),小于(<),大于(>),pipe(|),退格(\b),null(\ 0)和制表符(\ t).

方法并没有更好Path.GetInvalidPathChars.它包含完全相同的注释.


那么Path.GetInvalidFileNameChars有什么意义呢?我希望它能够准确地返回当前系统的无效字符,依靠.NET来了解我正在运行的文件系统并向我提供适合的无效字符.如果不是这种情况并且它只返回硬编码字符,这些字符首先不可靠,则应删除此方法,因为它的值为零.
@ fantastik78好点,但在这种情况下,我想要一个额外的枚举参数来指定我的远程FS.如果这是太多的维护工作(最有可能的情况),这整个方法仍然是一个坏主意,因为它给你错误的安全印象.

6> Lily Finley..:

对于文件名:

string cleanFileName = String.Join("", fileName.Split(Path.GetInvalidFileNameChars()));

对于完整路径:

string cleanPath = String.Join("", path.Split(Path.GetInvalidPathChars()));



7> user7116..:

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

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


我通常会同意第二个,但我有一个生成文件名的程序,在某些情况下可能包含非法字符.由于*我的程序*正在生成非法文件名,我认为删除/替换这些字符是合适的.(只是指出一个有效的用例)

8> Jeff Yates..:

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

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

然后我只需调用removeInvalidChars.Replace来执行查找和替换.这显然可以扩展到覆盖路径字符.


我还将添加一些可以在[MSDN](http://msdn.microsoft.com/zh-cn/library/aa365247.aspx#namespaces)上找到的其他无效文件名模式,并将您的解决方案扩展到以下正则表达式: `new Regex(String.Format(“ ^(CON | PRN | AUX | NUL | CLOCK \ $ | COM [1-9] | LPT [1-9])(?= \ .. | $)|(^( \。+ | \ s +)$)|((\。+ | \ s +)$)|([{{0}])“,Regex.Escape(new String(Path.GetInvalidFileNameChars()))),RegexOptions.Compiled | RegexOptions.Singleline | RegexOptions.CultureInvariant);`

9> anomepani..:

从用户输入中删除非法字符的最佳方法是使用Regex类替换非法字符,在代码后面创建方法,或者使用RegularExpression控件在客户端验证.

public string RemoveSpecialCharacters(string str)
{
    return Regex.Replace(str, "[^a-zA-Z0-9_]+", "_", RegexOptions.Compiled);
}

要么



恕我直言这个解决方案比其他人好得多,而不是搜索所有无效的字符,只需定义哪些是有效的.

10> Jan..:

我绝对更喜欢杰夫耶茨的想法.如果你稍微修改它,它将完美地工作:

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

改进只是为了逃避自动生成的正则表达式.



11> 小智..:

这是一个应该有助于.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, "");
    }
}



12> 小智..:

上面的大多数解决方案将路径和文件名的非法字符组合在一起是错误的(即使两个调用当前都返回相同的字符集).我首先在路径和文件名中拆分路径+文件名,然后将相应的设置应用于它们,然后再将两者合并.

wvd_vegt



13> Maxence..:

如果删除或替换单个字符的无效字符,则可能发生冲突:

 abc
>abc -> abc

这是一个避免这种情况的简单方法:

public static string ReplaceInvalidFileNameChars(string s)
{
    char[] invalidFileNameChars = System.IO.Path.GetInvalidFileNameChars();
    foreach (char c in invalidFileNameChars)
        s = s.Replace(c.ToString(), "[" + Array.IndexOf(invalidFileNameChars, c) + "]");
    return s;
}

结果:

  [1]abc
 >abc -> [2]abc



14> mirezus..:

抛出一个例外.

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

推荐阅读
家具销售_903
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有