मेरा कार्यक्रम इंटरनेट से मनमाना तार लेगा और उन्हें फ़ाइल नामों के लिए उपयोग करेगा। क्या इन तारों से बुरे पात्रों को हटाने का एक सरल तरीका है या क्या मुझे इसके लिए एक कस्टम फ़ंक्शन लिखने की आवश्यकता है?
मेरा कार्यक्रम इंटरनेट से मनमाना तार लेगा और उन्हें फ़ाइल नामों के लिए उपयोग करेगा। क्या इन तारों से बुरे पात्रों को हटाने का एक सरल तरीका है या क्या मुझे इसके लिए एक कस्टम फ़ंक्शन लिखने की आवश्यकता है?
जवाबों:
ऊ, मुझे इससे नफरत है जब लोग यह अनुमान लगाने की कोशिश करते हैं कि कौन से पात्र वैध हैं। पूरी तरह से गैर-पोर्टेबल होने (हमेशा मोनो के बारे में सोचने) के अलावा, पहले की दोनों टिप्पणियों में 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
अमान्य वर्णों को हटाने के लिए:
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());
अमान्य वर्णों को बदलने के लिए (और संभावित नाम संघर्ष जैसे नर्क * बनाम नर्क $) से बचें:
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());
यह सवाल किया गया है पूछा कई बार पहले और, के रूप में कई बार कहा से पहले, IO.Path.GetInvalidFileNameChars
पर्याप्त नहीं है।
सबसे पहले, PRN और CON जैसे कई नाम हैं जो आरक्षित हैं और फ़ाइल नाम के लिए अनुमत नहीं हैं। केवल रूट फ़ोल्डर में अन्य नाम नहीं हैं। एक अवधि में समाप्त होने वाले नामों को भी अनुमति नहीं है।
दूसरा, लंबाई की सीमाएं हैं। NTFS के लिए पूरी सूची यहां पढ़ें ।
तीसरा, आप उन फाइल सिस्टम से जुड़ सकते हैं जिनकी अन्य सीमाएँ हैं। उदाहरण के लिए, आईएसओ 9660 फाइलनाम "-" के साथ शुरू नहीं हो सकता है, लेकिन इसमें हो सकता है।
चौथा, यदि आप दो प्रक्रियाएं "मनमाने ढंग से" एक ही नाम से करते हैं, तो आप क्या करते हैं?
सामान्य तौर पर, फ़ाइल नामों के लिए बाहरी रूप से जनरेट किए गए नामों का उपयोग करना एक बुरा विचार है। मेरा सुझाव है कि अपने निजी फ़ाइल नाम पैदा करें और आंतरिक रूप से मानव-पठनीय नामों को संग्रहीत करें।
मैं ग्रेउनवुल्फ़ से सहमत हूँ और अत्यधिक सिफारिश करूँगा 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 - यह जितना होना चाहिए, उससे अधिक गूढ़ है - मैं संक्षिप्त होने की कोशिश कर रहा था।
Array.ForEach
सिर्फ foreach
यहाँ के बजाय उपयोग क्यों करेंगे
Path.GetInvalidFileNameChars().Aggregate(file, (current, c) => current.Replace(c, '-'))
यहाँ मेरा संस्करण है:
static string GetSafeFileName(string name, char replace = '_') {
char[] invalids = Path.GetInvalidFileNameChars();
return new string(name.Select(c => invalids.Contains(c) ? replace : c).ToArray());
}
मुझे यकीन नहीं है कि GetInvalidFileNameChars के परिणाम की गणना कैसे की जाती है, लेकिन "गेट" से पता चलता है कि यह गैर-तुच्छ है, इसलिए मैं परिणामों को कैश करता हूं। इसके अलावा, यह केवल इनपुट स्ट्रिंग को कई बार के बजाय एक बार बदल देता है, जैसे कि ऊपर दिए गए समाधान, जो अमान्य वर्णों के सेट पर पुनरावृति करते हैं, उन्हें एक समय में स्रोत स्ट्रिंग एक में प्रतिस्थापित करते हैं। इसके अलावा, मुझे कहाँ-आधारित समाधान पसंद हैं, लेकिन मैं उन्हें हटाने के बजाय अमान्य वर्णों को बदलना पसंद करता हूं। अंत में, मेरा प्रतिस्थापन एक चरित्र है जिसे स्ट्रिंग में परिवर्तित करने से पात्रों को परिवर्तित करने से बचने के लिए एक चरित्र है।
मैं कहता हूं कि सभी w / o प्रोफाइलिंग कर रहे हैं - यह एक "मुझे" अच्छा लगा। :)
new HashSet<char>(Path.GetInvalidFileNameChars())
हे (एन) गणना - सूक्ष्म अनुकूलन से बचने के लिए कर सकते हैं ।
यहां वह फ़ंक्शन है जो मैं अभी उपयोग कर रहा हूं (C # उदाहरण के लिए धन्यवाद jcollum):
public static string MakeSafeFilename(string filename, char replaceChar)
{
foreach (char c in System.IO.Path.GetInvalidFileNameChars())
{
filename = filename.Replace(c, replaceChar);
}
return filename;
}
मैंने इसे सुविधा के लिए "हेल्पर्स" क्लास में रखा।
यदि आप सभी विशेष वर्णों को जल्दी से निकालना चाहते हैं, जो कभी-कभी फ़ाइल नामों के लिए अधिक उपयोगकर्ता पठनीय होता है, तो यह अच्छी तरह से काम करता है:
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"
\W
गैर-अल्फा-न्यूमेरिक्स ( [^A-Za-z0-9_]
) से अधिक मेल खाता है । सभी यूनिकोड के शब्द 'अक्षर' (русский etc. ..., आदि) को भी प्रतिस्थापित नहीं किया जाएगा। लेकिन यह अच्छी बात है।
.
इसलिए आपको पहले एक्सटेंशन को निकालना होगा, और उसके बाद फिर से जोड़ना होगा।
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);
}
}
इस तरह स्ट्रिंग को बेस 64 के बराबर क्यों न करें:
string UnsafeFileName = "salmnas dlajhdla kjha;dmas'lkasn";
string SafeFileName = Convert.ToBase64String(Encoding.UTF8.GetBytes(UnsafeFileName));
यदि आप इसे वापस बदलना चाहते हैं तो आप इसे पढ़ सकते हैं:
UnsafeFileName = Encoding.UTF8.GetString(Convert.FromBase64String(SafeFileName));
मैंने इसका उपयोग पीएनजी फाइलों को एक यादृच्छिक विवरण से एक अद्वितीय नाम के साथ बचाने के लिए किया।
यहाँ पर मैंने अभी क्लिपफ्लेयर ( http://github.com/Zoomicon/ClipFlair ) StringExtensions static class (Utils.Silverlight प्रोजेक्ट) को जोड़ा है, जो कि डोर हाई आर्क द्वारा पोस्ट की गई संबंधित स्टैक्वेरफ़्लो से लिंक से एकत्रित जानकारी के आधार पर है:
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)
}
private void textBoxFileName_KeyPress(object sender, KeyPressEventArgs e)
{
e.Handled = CheckFileNameSafeCharacters(e);
}
/// <summary>
/// This is a good function for making sure that a user who is naming a file uses proper characters
/// </summary>
/// <param name="e"></param>
/// <returns></returns>
internal static bool CheckFileNameSafeCharacters(System.Windows.Forms.KeyPressEventArgs e)
{
if (e.KeyChar.Equals(24) ||
e.KeyChar.Equals(3) ||
e.KeyChar.Equals(22) ||
e.KeyChar.Equals(26) ||
e.KeyChar.Equals(25))//Control-X, C, V, Z and Y
return false;
if (e.KeyChar.Equals('\b'))//backspace
return false;
char[] charArray = Path.GetInvalidFileNameChars();
if (charArray.Contains(e.KeyChar))
return true;//Stop the character from being entered into the control since it is non-numerical
else
return false;
}
मुझे इसका उपयोग त्वरित और समझने में आसान लगता है:
<Extension()>
Public Function MakeSafeFileName(FileName As String) As String
Return FileName.Where(Function(x) Not IO.Path.GetInvalidFileNameChars.Contains(x)).ToArray
End Function
यह काम करता है एक वजह string
है IEnumerable
एक के रूप में char
देता है और वहाँ एक है string
निर्माता स्ट्रिंग है कि एक लेता है char
सरणी।
अपनी पुरानी परियोजनाओं से, मुझे यह समाधान मिल गया है, जो 2 वर्षों से पूरी तरह से काम कर रहा है। मैं "" के साथ अवैध वर्णों को प्रतिस्थापित कर रहा हूं, और फिर दोहरे के लिए जांच करूंगा! '
public string GetSafeFilename(string filename)
{
string res = string.Join("!", filename.Split(Path.GetInvalidFileNameChars()));
while (res.IndexOf("!!") >= 0)
res = res.Replace("!!", "!");
return res;
}
कई एएआरवी उपयोग करने का सुझाव देते हैं Path.GetInvalidFileNameChars()
जो मुझे एक बुरा समाधान की तरह लगता है। मैं आपको ब्लैक लिस्ट करने के बजाय व्हाइटलाइनिंग का उपयोग करने के लिए प्रोत्साहित करता हूं क्योंकि हैकर्स को हमेशा इसे बायपास करने का एक तरीका मिलेगा।
यहाँ कोड का एक उदाहरण है जिसका आप उपयोग कर सकते हैं:
string whitelist = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.";
foreach (char c in filename)
{
if (!whitelist.Contains(c))
{
filename = filename.Replace(c, '-');
}
}