मुझे "फू: बार" जैसा एक स्ट्रिंग मिला है जिसे मैं एक फ़ाइल नाम के रूप में उपयोग करना चाहता हूं, लेकिन विंडोज पर ":" चार का नाम एक फ़ाइलनाम में अनुमति नहीं है।
क्या कोई विधि है जो "फू: बार" को "फू-बार" की तरह बदल देगी?
मुझे "फू: बार" जैसा एक स्ट्रिंग मिला है जिसे मैं एक फ़ाइल नाम के रूप में उपयोग करना चाहता हूं, लेकिन विंडोज पर ":" चार का नाम एक फ़ाइलनाम में अनुमति नहीं है।
क्या कोई विधि है जो "फू: बार" को "फू-बार" की तरह बदल देगी?
जवाबों:
कुछ इस तरह की कोशिश करो:
string fileName = "something";
foreach (char c in System.IO.Path.GetInvalidFileNameChars())
{
fileName = fileName.Replace(c, '_');
}
संपादित करें:
चूंकि GetInvalidFileNameChars()
10 या 15 वर्ण वापस आएंगे, इसलिए StringBuilder
एक साधारण स्ट्रिंग के बजाय इसका उपयोग करना बेहतर है ; मूल संस्करण अधिक समय लगेगा और अधिक मेमोरी का उपभोग करेगा।
file.name.txt.pdf
एक वैध पीडीएफ है। विंडोज .
एक्सटेंशन के लिए केवल आखिरी पढ़ता है ।
fileName = fileName.Replace(":", "-")
हालांकि ":" विंडोज के लिए एकमात्र अवैध चरित्र नहीं है। आपको भी संभालना होगा:
/, \, :, *, ?, ", <, > and |
ये System.IO.Path.GetInvalidFileNameChars () में निहित हैं;
इसके अलावा (विंडोज पर), "।" केवल फ़ाइल नाम ("", "," .. "," ... ", और इसी तरह के अन्य वर्ण अमान्य नहीं हो सकते)। उदाहरण के लिए, "।" के साथ नामकरण करते समय सावधान रहें:
echo "test" > .test.
".Test" नामक एक फ़ाइल उत्पन्न करेगा
अंत में, यदि आप वास्तव में चीजों को सही ढंग से करना चाहते हैं , तो कुछ विशेष फ़ाइल नाम हैं जिनकी आपको आवश्यकता है। विंडोज पर आप नाम की फाइलें नहीं बना सकते हैं:
CON, PRN, AUX, CLOCK$, NUL
COM0, COM1, COM2, COM3, COM4, COM5, COM6, COM7, COM8, COM9
LPT0, LPT1, LPT2, LPT3, LPT4, LPT5, LPT6, LPT7, LPT8, and LPT9.
यह अधिक कुशल नहीं है, लेकिन यह अधिक मजेदार है :)
var fileName = "foo:bar";
var invalidChars = System.IO.Path.GetInvalidFileNameChars();
var cleanFileName = new string(fileName.Where(m => !invalidChars.Contains(m)).ToArray<char>());
यदि कोई इसके आधार पर अनुकूलित संस्करण चाहता है StringBuilder
, तो इसका उपयोग करें। एक विकल्प के रूप में rkagerer की चाल शामिल है।
static char[] _invalids;
/// <summary>Replaces characters in <c>text</c> that are not allowed in
/// file names with the specified replacement character.</summary>
/// <param name="text">Text to make into a valid filename. The same string is returned if it is valid already.</param>
/// <param name="replacement">Replacement character, or null to simply remove bad characters.</param>
/// <param name="fancy">Whether to replace quotes and slashes with the non-ASCII characters ” and ⁄.</param>
/// <returns>A string that can be used as a filename. If the output string would otherwise be empty, returns "_".</returns>
public static string MakeValidFileName(string text, char? replacement = '_', bool fancy = true)
{
StringBuilder sb = new StringBuilder(text.Length);
var invalids = _invalids ?? (_invalids = Path.GetInvalidFileNameChars());
bool changed = false;
for (int i = 0; i < text.Length; i++) {
char c = text[i];
if (invalids.Contains(c)) {
changed = true;
var repl = replacement ?? '\0';
if (fancy) {
if (c == '"') repl = '”'; // U+201D right double quotation mark
else if (c == '\'') repl = '’'; // U+2019 right single quotation mark
else if (c == '/') repl = '⁄'; // U+2044 fraction slash
}
if (repl != '\0')
sb.Append(repl);
} else
sb.Append(c);
}
if (sb.Length == 0)
return "_";
return changed ? sb.ToString() : text;
}
यहाँ Linq
जो उपयोग करता है स्वीकृत उत्तर का एक संस्करण है Enumerable.Aggregate
:
string fileName = "something";
Path.GetInvalidFileNameChars()
.Aggregate(fileName, (current, c) => current.Replace(c, '_'));
डिएगो के पास सही समाधान है लेकिन वहां एक बहुत छोटी गलती है। String .eplace का उपयोग किया जा रहा है string.eplace (char, char) का संस्करण होना चाहिए, एक string नहीं है। रीप्ले (char, string)
मैं उत्तर को संपादित नहीं कर सकता या मैंने केवल मामूली बदलाव किया होगा।
तो यह होना चाहिए:
string fileName = "something";
foreach (char c in System.IO.Path.GetInvalidFileNameChars())
{
fileName = fileName.Replace(c, '_');
}
यहाँ डिएगो के उत्तर पर एक हल्का मोड़ है।
यदि आप यूनिकोड से डरते नहीं हैं, तो आप अमान्य यूनिकोड प्रतीकों के साथ अमान्य वर्णों को प्रतिस्थापित करके थोड़ी अधिक निष्ठा बनाए रख सकते हैं। यहाँ हाल ही में एक परियोजना का उपयोग किया गया है जिसमें लंबर कटलिस्ट शामिल हैं:
static string MakeValidFilename(string text) {
text = text.Replace('\'', '’'); // U+2019 right single quotation mark
text = text.Replace('"', '”'); // U+201D right double quotation mark
text = text.Replace('/', '⁄'); // U+2044 fraction slash
foreach (char c in System.IO.Path.GetInvalidFileNameChars()) {
text = text.Replace(c, '_');
}
return text;
}
यह के 1⁄2” spruce.txt
बजाय filenames पैदा करता है1_2_ spruce.txt
हाँ, यह वास्तव में काम करता है:
कैविएट एम्प्टर
मुझे पता था कि यह ट्रिक NTFS पर काम करेगी, लेकिन यह जानकर आश्चर्य हुआ कि यह FAT और FAT32 विभाजन पर भी काम करती है। ऐसा इसलिए है क्योंकि लंबे फाइलनाम यूनिकोड में संग्रहीत हैं , यहां तक कि विंडोज 95 / एनटी के रूप में भी। मैंने Win7, XP और यहां तक कि एक लिनक्स-आधारित राउटर पर परीक्षण किया और उन्होंने ओके दिखाया। DOSBox के अंदर के लिए समान नहीं कह सकते।
इससे पहले कि आप इसके साथ पागल हो जाएं, विचार करें कि क्या आपको वास्तव में अतिरिक्त निष्ठा की आवश्यकता है। यूनिकोड लुक-बाइक्स लोगों या पुराने कार्यक्रमों को भ्रमित कर सकता है, जैसे पुराने ओएस के कोडपेज पर निर्भर ।
यहां एक संस्करण है जो पूर्ण दक्षता के लिए उपयोग करता है StringBuilder
और IndexOfAny
थोक परिशिष्ट के साथ है। यह डुप्लिकेट स्ट्रिंग बनाने के बजाय मूल स्ट्रिंग भी लौटाता है।
अंतिम लेकिन कम से कम, इसमें एक स्विच स्टेटमेंट है जो लुक-अलाइक पात्रों को लौटाता है जिसे आप अपनी इच्छानुसार किसी भी तरह से अनुकूलित कर सकते हैं। चेक बाहर Unicode.org के confusables देखने फ़ॉन्ट के आधार पर देखने के लिए क्या विकल्प हो सकता है,।
public static string GetSafeFilename(string arbitraryString)
{
var invalidChars = System.IO.Path.GetInvalidFileNameChars();
var replaceIndex = arbitraryString.IndexOfAny(invalidChars, 0);
if (replaceIndex == -1) return arbitraryString;
var r = new StringBuilder();
var i = 0;
do
{
r.Append(arbitraryString, i, replaceIndex - i);
switch (arbitraryString[replaceIndex])
{
case '"':
r.Append("''");
break;
case '<':
r.Append('\u02c2'); // '˂' (modifier letter left arrowhead)
break;
case '>':
r.Append('\u02c3'); // '˃' (modifier letter right arrowhead)
break;
case '|':
r.Append('\u2223'); // '∣' (divides)
break;
case ':':
r.Append('-');
break;
case '*':
r.Append('\u2217'); // '∗' (asterisk operator)
break;
case '\\':
case '/':
r.Append('\u2044'); // '⁄' (fraction slash)
break;
case '\0':
case '\f':
case '?':
break;
case '\t':
case '\n':
case '\r':
case '\v':
r.Append(' ');
break;
default:
r.Append('_');
break;
}
i = replaceIndex + 1;
replaceIndex = arbitraryString.IndexOfAny(invalidChars, i);
} while (replaceIndex != -1);
r.Append(arbitraryString, i, arbitraryString.Length - i);
return r.ToString();
}
यह जांच नहीं की जाती .
, ..
या की तरह आरक्षित नाम CON
है क्योंकि यह स्पष्ट नहीं है कि क्या प्रतिस्थापन होना चाहिए।
मेरे कोड को थोड़ा साफ करना और थोड़ा रिफलेक्ट करना ... मैंने स्ट्रिंग प्रकार के लिए एक एक्सटेंशन बनाया:
public static string ToValidFileName(this string s, char replaceChar = '_', char[] includeChars = null)
{
var invalid = Path.GetInvalidFileNameChars();
if (includeChars != null) invalid = invalid.Union(includeChars).ToArray();
return string.Join(string.Empty, s.ToCharArray().Select(o => o.In(invalid) ? replaceChar : o));
}
अब इसके साथ प्रयोग करना आसान है:
var name = "Any string you want using ? / \ or even +.zip";
var validFileName = name.ToValidFileName();
यदि आप "_" की तुलना में एक अलग चार्ट के साथ बदलना चाहते हैं, तो आप उपयोग कर सकते हैं:
var validFileName = name.ToValidFileName(replaceChar:'#');
और आप बदलने के लिए वर्ण जोड़ सकते हैं .. उदाहरण के लिए आप रिक्त स्थान या अल्पविराम नहीं चाहते हैं:
var validFileName = name.ToValidFileName(includeChars: new [] { ' ', ',' });
आशा करता हूँ की ये काम करेगा...
चियर्स
एक और सरल उपाय:
private string MakeValidFileName(string original, char replacementChar = '_')
{
var invalidChars = new HashSet<char>(Path.GetInvalidFileNameChars());
return new string(original.Select(c => invalidChars.Contains(c) ? replacementChar : c).ToArray());
}
एक सरल एक लाइन कोड:
var validFileName = Path.GetInvalidFileNameChars().Aggregate(fileName, (f, c) => f.Replace(c, '_'));
यदि आप इसे पुन: उपयोग करना चाहते हैं, तो आप इसे एक्सटेंशन विधि में लपेट सकते हैं।
public static string ToValidFileName(this string fileName) => Path.GetInvalidFileNameChars().Aggregate(fileName, (f, c) => f.Replace(c, '_'));
मुझे एक ऐसी प्रणाली की आवश्यकता थी जो टकराव पैदा न कर सके इसलिए मैं एक से अधिक वर्णों को मैप नहीं कर सकता था। मैं इसके साथ समाप्त हुआ:
public static class Extension
{
/// <summary>
/// Characters allowed in a file name. Note that curly braces don't show up here
/// becausee they are used for escaping invalid characters.
/// </summary>
private static readonly HashSet<char> CleanFileNameChars = new HashSet<char>
{
' ', '!', '#', '$', '%', '&', '\'', '(', ')', '+', ',', '-', '.',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '=', '@',
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
'[', ']', '^', '_', '`',
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
};
/// <summary>
/// Creates a clean file name from one that may contain invalid characters in
/// a way that will not collide.
/// </summary>
/// <param name="dirtyFileName">
/// The file name that may contain invalid filename characters.
/// </param>
/// <returns>
/// A file name that does not contain invalid filename characters.
/// </returns>
/// <remarks>
/// <para>
/// Escapes invalid characters by converting their ASCII values to hexadecimal
/// and wrapping that value in curly braces. Curly braces are escaped by doubling
/// them, for example '{' => "{{".
/// </para>
/// <para>
/// Note that although NTFS allows unicode characters in file names, this
/// method does not.
/// </para>
/// </remarks>
public static string CleanFileName(this string dirtyFileName)
{
string EscapeHexString(char c) =>
"{" + (c > 255 ? $"{(uint)c:X4}" : $"{(uint)c:X2}") + "}";
return string.Join(string.Empty,
dirtyFileName.Select(
c =>
c == '{' ? "{{" :
c == '}' ? "}}" :
CleanFileNameChars.Contains(c) ? $"{c}" :
EscapeHexString(c)));
}
}
मुझे आज ऐसा करने की आवश्यकता थी ... मेरे मामले में, मुझे एक अंतिम .km फ़ाइल के लिए दिनांक और समय के साथ एक ग्राहक नाम को संक्षिप्त करने की आवश्यकता थी। मेरा अंतिम समाधान यह था:
string name = "Whatever name with valid/invalid chars";
char[] invalid = System.IO.Path.GetInvalidFileNameChars();
string validFileName = string.Join(string.Empty,
string.Format("{0}.{1:G}.kmz", name, DateTime.Now)
.ToCharArray().Select(o => o.In(invalid) ? '_' : o));
यदि आप रिक्त स्थान को अवैध सरणी में जोड़ते हैं, तो आप इसे रिक्त स्थान भी बदल सकते हैं।
शायद यह सबसे तेज़ नहीं है, लेकिन जैसा कि प्रदर्शन एक मुद्दा नहीं था, मैंने इसे सुरुचिपूर्ण और समझने योग्य पाया।
चीयर्स!
आप यह एक sed
आदेश के साथ कर सकते हैं :
sed -e "
s/[?()\[\]=+<>:;©®”,*|]/_/g
s/"$'\t'"/ /g
s/–/-/g
s/\"/_/g
s/[[:cntrl:]]/_/g"