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

有没有办法在c#中使字符串文件路径安全?

如何解决《有没有办法在c#中使字符串文件路径安全?》经验,为你挑选了10个好方法。

我的程序将从互联网上获取任意字符串并将其用于文件名.有没有一种简单的方法从这些字符串中删除坏字符或我是否需要为此编写自定义函数?



1> Jonathan All..:

呃,当人们试图猜测哪些角色有效时,我讨厌它.除了完全不可移植(总是考虑Mono)之外,两个早期的评论都错过了25个无效字符.

'Clean just a filename
Dim filename As String = "salmnas dlajhdla kjha;dmas'lkasn"
For Each c In IO.Path.GetInvalidFileNameChars
    filename = filename.Replace(c, "")
Next

'See also IO.Path.GetInvalidPathChars


C#版本:foreach(在Path.GetInvalidFileNameChars()中的var c){fileName = fileName.Replace(c,' - '); }
该解决方案如何处理名称冲突?似乎多个字符串可以匹配单个文件名(例如"Hell?"和"Hell*").如果你只是删除违规的字符那么好; 否则你需要小心处理名称冲突.
一个衬里,为了有趣的结果= Path.GetInvalidFileNameChars().聚合(结果,(当前,c)=> current.Replace(c,' - '));
那么filesytem的名称(和路径)长度限制呢?保留文件名(PRN CON)怎么样?如果您需要存储数据和原始名称,您可以使用带有Guid名称的2个文件:guid.txt和guid.dat

2> Squirrel..:

要删除无效字符:

static readonly char[] invalidFileNameChars = Path.GetInvalidFileNameChars();

// Builds a string out of valid chars
var validFilename = new string(filename.Where(ch => !invalidFileNameChars.Contains(ch)).ToArray());

要替换无效字符:

static readonly char[] invalidFileNameChars = Path.GetInvalidFileNameChars();

// Builds a string out of valid chars and an _ for invalid ones
var validFilename = new string(filename.Select(ch => invalidFileNameChars.Contains(ch) ? '_' : ch).ToArray());

要替换无效字符(并避免潜在的名称冲突,如Hell*vs Hell $):

static readonly IList invalidFileNameChars = Path.GetInvalidFileNameChars();

// Builds a string out of valid chars and replaces invalid chars with a unique letter (Moves the Char into the letter range of unicode, starting at "A")
var validFilename = new string(filename.Select(ch => invalidFileNameChars.Contains(ch) ? Convert.ToChar(invalidFileNameChars.IndexOf(ch) + 65) : ch).ToArray());



3> Dour High Ar..:

这个问题已经被问很多 次 之前,正如之前多次指出,IO.Path.GetInvalidFileNameChars是不够的.

首先,有许多名称,如PRN和CON,这些名称是保留的,不允许用于文件名.还有其他名称不允许仅在根文件夹中.也不允许以句点结尾的名称.

其次,存在各种长度限制.在这里阅读NTFS的完整列表.

第三,您可以附加到具有其他限制的文件系统.例如,ISO 9660文件名不能以" - "开头,但可以包含它.

第四,如果两个进程"任意"选择相同的名称,你会怎么做?

通常,使用外部生成的文件名名称是个坏主意.我建议生成您自己的私有文件名并在内部存储人类可读的名称.


尽管您在技术上是准确的,但GetInvalidFileNameChars适用于您使用它的80%以上的情况,因此它是一个很好的答案.作为对我认为接受的答案的评论,你的回答会更合适.
我同意DourHighArch.将文件内部保存为guid,引用存储在数据库中的"友好名称".不要让用户控制您在网站上的路径,否则他们会试图窃取您的web.config.如果您使用url重写来使其清理,它将仅适用于数据库中匹配的友好URL.

4> Aaron Wagner..:

我同意Grauenwolf并强烈推荐 Path.GetInvalidFileNameChars()

这是我的C#贡献:

string file = @"38?/.\}[+=n a882 a.a*/|n^%$ ad#(-))";
Array.ForEach(Path.GetInvalidFileNameChars(), 
      c => file = file.Replace(c.ToString(), String.Empty));

ps - 这比它应该更加神秘 - 我试图简洁.


如果你想更简洁/更神秘:`Path.GetInvalidFileNameChars().Aggregate(file,(current,c)=> current.Replace(c,' - '))`
@rbuddicom Array.ForEach接受一个委托,这意味着它需要调用一个无法内联的函数.对于短字符串,最终可能会花费更多时间在函数调用开销上而不是实际逻辑上..NET Core正在研究"去虚拟化"调用的方法,从而减少开销.
为什么在世界上你会使用`Array.ForEach`而不仅仅是'foreach`

5> csells..:

这是我的版本:

static string GetSafeFileName(string name, char replace = '_') {
  char[] invalids = Path.GetInvalidFileNameChars();
  return new string(name.Select(c => invalids.Contains(c) ? replace : c).ToArray());
}

我不确定如何计算GetInvalidFileNameChars的结果,但"Get"表明它是非平凡的,所以我缓存了结果.此外,这只会遍历输入字符串一次而不是多次,就像上面的迭代遍历无效字符集的解决方案一样,在源字符串中一次替换它们.此外,我喜欢基于位置的解决方案,但我更喜欢替换无效的字符而不是删除它们.最后,我的替换只是一个字符,以避免在迭代字符串时将字符转换为字符串.

我说所有这些都没有进行分析 - 这个对我来说"感觉"很好.:)



6> sidewindergu..:

这是我现在使用的功能(感谢jcollum用于C#示例):

public static string MakeSafeFilename(string filename, char replaceChar)
{
    foreach (char c in System.IO.Path.GetInvalidFileNameChars())
    {
        filename = filename.Replace(c, replaceChar);
    }
    return filename;
}

为了方便起见,我把它放在"助手"课程中.



7> Keith..:

如果你想快速删除所有特殊字符,这些特殊字符有时候用户可以读取文件名,这很有效:

string myCrazyName = "q`w^e!r@t#y$u%i^o&p*a(s)d_f-g+h=j{k}l|z:x\"cb?n[m]q\\w;e'r,t.y/u";
string safeName = Regex.Replace(
    myCrazyName,
    "\W",  /*Matches any nonword character. Equivalent to '[^A-Za-z0-9_]'*/
    "",
    RegexOptions.IgnoreCase);
// safeName == "qwertyuiopasd_fghjklzxcvbnmqwertyu"



8> Ronnie Overb..:
static class Utils
{
    public static string MakeFileSystemSafe(this string s)
    {
        return new string(s.Where(IsFileSystemSafe).ToArray());
    }

    public static bool IsFileSystemSafe(char c)
    {
        return !Path.GetInvalidFileNameChars().Contains(c);
    }
}



9> George Birbi..:

这是我刚刚添加到ClipFlair(http://github.com/Zoomicon/ClipFlair)StringExtensions静态类(Utils.Silverlight项目)的内容,基于从Dour High Arch上面发布的相关stackoverflow问题的链接收集的信息:

public static string ReplaceInvalidFileNameChars(this string s, string replacement = "")
{
  return Regex.Replace(s,
    "[" + Regex.Escape(new String(System.IO.Path.GetInvalidPathChars())) + "]",
    replacement, //can even use a replacement string of any length
    RegexOptions.IgnoreCase);
    //not using System.IO.Path.InvalidPathChars (deprecated insecure API)
}



10> 小智..:

为什么不将字符串转换为像这样的Base64等效项:

string UnsafeFileName = "salmnas dlajhdla kjha;dmas'lkasn";
string SafeFileName = Convert.ToBase64String(Encoding.UTF8.GetBytes(UnsafeFileName));

如果您想将其转换回去,可以阅读以下内容:

UnsafeFileName = Encoding.UTF8.GetString(Convert.FromBase64String(SafeFileName));

我用它来保存来自随机描述的具有唯一名称的PNG文件。

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