有没有办法在 C# 中使字符串文件路径安全?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/333175/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Is there a way of making strings file-path safe in c#?
提问by Martin Doms
My program will take arbitrary strings from the internet and use them for file names. Is there a simple way to remove the bad characters from these strings or do I need to write a custom function for this?
我的程序将从互联网上获取任意字符串并将它们用作文件名。有没有一种简单的方法可以从这些字符串中删除坏字符,或者我是否需要为此编写自定义函数?
采纳答案by Jonathan Allen
Ugh, I hate it when people try to guess at which characters are valid. Besides being completely non-portable (always thinking about Mono), both of the earlier comments missed more 25 invalid characters.
呃,当人们试图猜测哪些字符有效时,我讨厌它。除了完全不可移植(总是考虑 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
回答by Aaron Wagner
I agree with Grauenwolf and would highly recommend the Path.GetInvalidFileNameChars()
我同意 Grauenwolf 并强烈推荐 Path.GetInvalidFileNameChars()
Here's my C# contribution:
这是我的 C# 贡献:
string file = @"38?/.\}[+=n a882 a.a*/|n^%$ ad#(-))";
Array.ForEach(Path.GetInvalidFileNameChars(),
c => file = file.Replace(c.ToString(), String.Empty));
p.s. -- this is more cryptic than it should be -- I was trying to be concise.
ps——这比它应该的更神秘——我试图简洁。
回答by Keith
If you want to quickly strip out all special characters which is sometimes more user readable for file names this works nicely:
如果您想快速删除所有特殊字符,这些特殊字符有时对文件名更易读,这很好用:
string myCrazyName = "q`w^e!r@t#y$u%i^o&p*a(s)d_f-g+h=j{k}l|z:x\"c<v>b?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"
回答by sidewinderguy
Here's the function that I am using now (thanks jcollum for the C# example):
这是我现在使用的函数(感谢 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;
}
I just put this in a "Helpers" class for convenience.
为方便起见,我只是将它放在“Helpers”类中。
回答by Squirrel
To strip invalid characters:
去除无效字符:
static readonly char[] invalidFileNameChars = Path.GetInvalidFileNameChars();
// Builds a string out of valid chars
var validFilename = new string(filename.Where(ch => !invalidFileNameChars.Contains(ch)).ToArray());
To replace invalid characters:
替换无效字符:
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());
To replace invalid characters (and avoid potential name conflict like Hell* vs Hell$):
替换无效字符(并避免潜在的名称冲突,如 Hell* 与 Hell$):
static readonly IList<char> 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());
回答by Dour High Arch
This question has been asked manytimesbeforeand, as pointed out many times before, IO.Path.GetInvalidFileNameChars
is not adequate.
这个问题已经被问很多次之前,正如多次指出之前,IO.Path.GetInvalidFileNameChars
是不够的。
First, there are many names like PRN and CON that are reserved and not allowed for filenames. There are other names not allowed only at the root folder. Names that end in a period are also not allowed.
首先,有许多像 PRN 和 CON 这样的名称是保留的,不允许用作文件名。还有其他名称不允许仅在根文件夹中使用。也不允许以句点结尾的名称。
Second, there are a variety of length limitations. Read the full list for NTFS here.
其次,有多种长度限制。在此处阅读 NTFS 的完整列表。
Third, you can attach to filesystems that have other limitations. For example, ISO 9660 filenames cannot start with "-" but can contain it.
第三,您可以附加到具有其他限制的文件系统。例如,ISO 9660 文件名不能以“-”开头,但可以包含它。
Fourth, what do you do if two processes "arbitrarily" pick the same name?
第四,如果两个进程“任意”取同名怎么办?
In general, using externally-generated names for file names is a bad idea. I suggest generating your own private file names and storing human-readable names internally.
通常,将外部生成的名称用于文件名是一个坏主意。我建议生成您自己的私有文件名并在内部存储人类可读的名称。
回答by cjbarth
I find using this to be quick and easy to understand:
我发现使用它可以快速且易于理解:
<Extension()>
Public Function MakeSafeFileName(FileName As String) As String
Return FileName.Where(Function(x) Not IO.Path.GetInvalidFileNameChars.Contains(x)).ToArray
End Function
This works because a string
is IEnumerable
as a char
array and there is a string
constructor string that takes a char
array.
这是有效的,因为 astring
是IEnumerable
一个char
数组,并且有一个string
接受char
数组的构造函数字符串。
回答by Ronnie Overby
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);
}
}
回答by George Birbilis
Here's what I just added to ClipFlair's (http://github.com/Zoomicon/ClipFlair) StringExtensions static class (Utils.Silverlight project), based on info gathered from the links to related stackoverflow questions posted by Dour High Arch above:
这是我刚刚添加到 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)
}
回答by csells
Here's my version:
这是我的版本:
static string GetSafeFileName(string name, char replace = '_') {
char[] invalids = Path.GetInvalidFileNameChars();
return new string(name.Select(c => invalids.Contains(c) ? replace : c).ToArray());
}
I'm not sure how the result of GetInvalidFileNameChars is calculated, but the "Get" suggests it's non-trivial, so I cache the results. Further, this only traverses the input string once instead of multiple times, like the solutions above that iterate over the set of invalid chars, replacing them in the source string one at a time. Also, I like the Where-based solutions, but I prefer to replace invalid chars instead of removing them. Finally, my replacement is exactly one character to avoid converting characters to strings as I iterate over the string.
我不确定 GetInvalidFileNameChars 的结果是如何计算的,但“Get”表明它很重要,所以我缓存了结果。此外,这只遍历输入字符串一次而不是多次,就像上面迭代无效字符集的解决方案一样,一次在源字符串中替换它们。另外,我喜欢基于 Where 的解决方案,但我更喜欢替换无效字符而不是删除它们。最后,我的替换正好是一个字符,以避免在我遍历字符串时将字符转换为字符串。
I say all that w/o doing the profiling -- this one just "felt" nice to me. : )
我说了所有没有做分析的事情——这个对我来说“感觉”很好。:)