একটি স্বেচ্ছাসেবী স্ট্রিং থেকে একটি বৈধ উইন্ডোজ ফাইলের নাম কিভাবে?


97

আমি "ফু: বার" এর মতো একটি স্ট্রিং পেয়েছি যা আমি একটি ফাইলের নাম হিসাবে ব্যবহার করতে চাই, তবে উইন্ডোজে ":" চর কোনও ফাইলের নামেই অনুমোদিত নয়।

এমন কোনও পদ্ধতি আছে যা "ফু: বার" কে "ফু-বার" এর মতো কিছুতে পরিণত করবে?


4
আমি আজ এই একই জিনিস করেছি। আমি কোনও কারণে এসও চেক করিনি, তবে যাইহোক উত্তর খুঁজে পেয়েছি।
অ্যারন স্মিথ

উত্তর:


155

এরকম কিছু চেষ্টা করুন:

string fileName = "something";
foreach (char c in System.IO.Path.GetInvalidFileNameChars())
{
   fileName = fileName.Replace(c, '_');
}

সম্পাদনা করুন:

যেহেতু GetInvalidFileNameChars()10 বা 15 অক্ষর ফেরত আসবে StringBuilder, একটি সরল স্ট্রিংয়ের পরিবর্তে এটি ব্যবহার করা ভাল ; আসল সংস্করণটি বেশি সময় নিবে এবং আরও মেমরি গ্রহণ করবে।


4
আপনি যদি চান তবে আপনি একটি স্ট্রিংবিল্ডার ব্যবহার করতে পারেন, তবে নামগুলি সংক্ষিপ্ত হয় এবং আমি অনুমান করি যে এটি উপযুক্ত নয়। আপনি একটি চর তৈরি করার জন্য আপনার নিজস্ব পদ্ধতিও তৈরি করতে পারেন [] এবং সমস্ত ভুল অক্ষরকে একটি পুনরাবৃত্তিতে প্রতিস্থাপন করতে পারেন। সর্বদা এটা সহজ যদি না তা না কাজ না হয়, আপনি খারাপ বোতল ঘাড়ে থাকতে পারে রাখার উত্তম
দিয়েগো Jancic

4
অবৈধফিনেমেচারস = নতুন চর [] char '"', '<', '>', '|', '\ 0', '\ x0001', '\ x0002', '\ x0003', '\ x0004', '\ x0005 ',' \ x0006 ',' \ a ',' \ বি ',' \ টি ',' \ n ',' \ ভি ',' \ ফ ',' \ আর ',' \ x000e ',' \ x000f ',' \ x0010 ',' \ x0011 ',' \ x0012 ',' \ x0013 ',' \ x0014 ',' \ x0015 ',' \ x0016 ',' \ x0017 ',' \ x0018 ',' \ x0019 ',' \ x001a ',' \ x001 বি ',' \ x001c ',' \ x001 ডি ',' \ x001e ',' \ x001f ',': ',' * ','? ',' \\ ', '/'};
দিয়েগো জানিক

9
স্ট্রিংয়ে 2+ ভিন্ন অবৈধ অক্ষর থাকার সম্ভাবনা এতটাই ছোট যে স্ট্রিংয়ের পারফরম্যান্স সম্পর্কে যত্নশীল ep প্রতিস্থাপন () অর্থহীন।
সার্জ ওয়াটিয়ার

4
দুর্দান্ত সমাধান, এক্ষেত্রে আকর্ষণীয়, পুনরায় ভাগ করা এই লিনক সংস্করণটির পরামর্শ দিয়েছে: ফাইলনাম = সিস্টেম.আইও.প্যাথ.গেটআইনডাওলফিলনেমচার্স ()। সমষ্টি (ফাইলনাম, (বর্তমান, সি) => বর্তমান.পরিবর্তন (সি, '_')); আমি ভাবছি সেখানে কোনও সম্ভাব্য পারফরম্যান্সের উন্নতি হয়েছে কিনা। পারফরম্যান্স আমার সবচেয়ে বড় উদ্বেগ নয় বলে আমি পঠনযোগ্যতার জন্য মূলটি রেখেছি। তবে যদি কেউ আগ্রহী হন, তবে বেঞ্চমার্কিংয়ের জন্য মূল্যবান হতে পারে
chrispepper1989

4
@ অ্যান্ডিমের দরকার নেই। file.name.txt.pdfএকটি বৈধ পিডিএফ। উইন্ডোজ কেবল .এক্সটেনশনের জন্য শেষটি পড়ে ।
দিয়েগো জ্যানিক

33
fileName = fileName.Replace(":", "-") 

তবে ":" উইন্ডোজের একমাত্র অবৈধ চরিত্র নয়। আপনাকেও পরিচালনা করতে হবে:

/, \, :, *, ?, ", <, > and |

এগুলি System.IO.Path.GetInuthorFileNameChars () এ অন্তর্ভুক্ত রয়েছে;

এছাড়াও (উইন্ডোজে), "। ফাইলের নামের একমাত্র অক্ষর হতে পারে না (উভয় "।", "..", "..." এবং আরও অবৈধ)। "।" দিয়ে ফাইলের নামকরণের সময় সতর্ক থাকুন, উদাহরণস্বরূপ:

echo "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.

4
সংরক্ষিত নামগুলি সম্পর্কে আমি কখনই জানতাম না। যদিও বোঝায়
গ্রেগ ডিন

4
এছাড়াও, এর মূল্য কী, আপনি দশমিকের পরে এই সংরক্ষিত নামগুলির একটি দিয়ে শুরু করে কোনও ফাইল নাম তৈরি করতে পারবেন না। ie con.air.avi
জন কনরাড

".foo" একটি বৈধ ফাইলের নাম। "CON" ফাইলের নাম সম্পর্কে জানতেন না - এটি কীসের জন্য?
Configurator

যে আঁচড়ের দাগ. কন কনসোল জন্য।
Configurator

ধন্যবাদ কনফিগার; আমি উত্তর আপডেট করেছি, আপনি সঠিক ".foo" বৈধ; তবে ".ফু।" সম্ভব, অবাঞ্ছিত ফলাফল বাড়ে। আপডেট হয়েছে।
ফিল দাম 0

13

এটি আরও দক্ষ নয়, তবে এটি আরও মজাদার :)

var fileName = "foo:bar";
var invalidChars = System.IO.Path.GetInvalidFileNameChars();
var cleanFileName = new string(fileName.Where(m => !invalidChars.Contains(m)).ToArray<char>());

12

যদি কেউ এর উপর ভিত্তি করে একটি অনুকূলিত সংস্করণ চায় তবে এটি 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;
}

সুন্দর এবং পঠনযোগ্য কোডের জন্য +1। বাগগুলি পড়তে ও লক্ষ্য করা খুব সহজ করে তোলে: পি .. এই ক্রিয়াকলাপটি সর্বদা আসল স্ট্রিংটি ফিরে আসবে কারণ পরিবর্তন কখনও সত্য হবে না।
এর্তি-ক্রিস ইলমা

ধন্যবাদ, আমি মনে করি এটি এখন আরও ভাল। ওপেন সোর্স সম্পর্কে তারা কী বলেছে তা আপনি জানেন, "অনেক চোখ সমস্ত বাগ অগভীর করে তোলে তাই আমাকে ইউনিট পরীক্ষা লিখতে হবে না" ...
কিওয়ার্টি

8

দিয়েগো এর উত্তরে এখানে সামান্য মোচড় দেওয়া।

আপনি যদি ইউনিকোড থেকে ভয় পান না, আপনি অবৈধ অক্ষরগুলির সাথে সাদৃশ্যপূর্ণ বৈধ ইউনিকোড চিহ্নগুলি প্রতিস্থাপন করে কিছুটা বিশ্বস্ততা বজায় রাখতে পারবেন। কাঠের কাটলিস্টগুলির সাথে জড়িত একটি সাম্প্রতিক প্রকল্পে আমি কোডটি এখানে ব্যবহার করেছি:

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পরিবর্তে ফাইলের মতো উত্পাদন করে1_2_ spruce.txt

হ্যাঁ, এটি সত্যিই কাজ করে:

এক্সপ্লোরার নমুনা

ক্যাভেট এমপোটার

আমি জানতাম যে এই কৌশলটি এনটিএফএসে কাজ করবে তবে অবাক হয়েছিল যে এটি FAT এবং FAT32 পার্টিশনেও কাজ করে। এর কারণ লং ফাইলের নামের করছে ইউনিকোড সঞ্চিত , এমনকি হিসাবে পর্যন্ত ফিরে উইন্ডোজ 95 / NT তে হিসাবে। আমি উইন 7, এক্সপি, এমনকি একটি লিনাক্স-ভিত্তিক রাউটারেও পরীক্ষা করেছি এবং তারা ঠিক আছে showed ডসবক্সের ভিতরে একই কথা বলতে পারি না।

এটি বলেছিল, আপনি এর সাথে বাদাম দেওয়ার আগে আপনার সত্যিকারের অতিরিক্ত বিশ্বস্ততা দরকার কিনা তা বিবেচনা করুন। ইউনিকোড চেহারা-পছন্দগুলি মানুষ বা পুরানো প্রোগ্রামগুলিকে বিভ্রান্ত করতে পারে, যেমন পুরানো ওএসের কোডপেজের উপর নির্ভরশীল ।


8

Linqযা ব্যবহার করে স্বীকৃত উত্তরের একটি সংস্করণ এখানে রয়েছে Enumerable.Aggregate:

string fileName = "something";

Path.GetInvalidFileNameChars()
    .Aggregate(fileName, (current, c) => current.Replace(c, '_'));

7

দিয়েগো সঠিক সমাধান আছে কিন্তু সেখানে একটি খুব ছোট ভুল আছে। স্ট্রিংয়ের সংস্করণ used প্রতিস্থাপনটি স্ট্রিং হওয়া উচিত ep প্রতিস্থাপন (চর, চর), স্ট্রিং নেই ep প্রতিস্থাপন (চর, স্ট্রিং)

আমি উত্তরটি সম্পাদনা করতে পারি না বা আমি কেবল সামান্য পরিবর্তন করতে পারি।

সুতরাং এটি হওয়া উচিত:

string fileName = "something";
foreach (char c in System.IO.Path.GetInvalidFileNameChars())
{
   fileName = fileName.Replace(c, '_');
}

5

এটি ব্যবহার করে এমন একটি সংস্করণ StringBuilderIndexOfAny সম্পূর্ণ দক্ষতার জন্য এবং বাল্ক সংযোজন সহ। এটি ডুপ্লিকেট স্ট্রিং তৈরি না করে মূল স্ট্রিংটিও প্রদান করে।

সর্বশেষে তবে অন্তত নয়, এতে একটি স্যুইচ স্টেটমেন্ট রয়েছে যা দেখতে অনুরূপ অক্ষরগুলি দেয় যা আপনি নিজের ইচ্ছামত যে কোনও উপায়ে কাস্টমাইজ করতে পারেন। চেক আউট 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


3

আমার কোডটি একটু পরিষ্কার করে এবং কিছুটা রিফ্যাক্টরিং করা হচ্ছে ... আমি স্ট্রিং টাইপের জন্য একটি এক্সটেনশন তৈরি করেছি:

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 [] { ' ', ',' });

আশা করি এটা সাহায্য করবে...

চিয়ার্স


3

আর একটি সহজ সমাধান:

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

3

একটি সাধারণ একটি লাইন কোড:

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, '_'));

1

আমার এমন একটি সিস্টেমের দরকার ছিল যা সংঘর্ষ তৈরি করতে না পারে তাই আমি একের সাথে একাধিক অক্ষর মানচিত্র করতে পারি না। আমি এখানে দিয়ে শেষ করেছি:

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

0

আমার আজ এটি করা দরকার ... আমার ক্ষেত্রে আমার একটি চূড়ান্ত .kmz ফাইলের জন্য তারিখ এবং সময় সহ গ্রাহকের নামকে বোঝাতে হবে। আমার চূড়ান্ত সমাধানটি হ'ল:

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

আপনি যদি অবৈধ অ্যারেতে স্পেস চরটি যুক্ত করেন তবে আপনি এটি স্পেসগুলি প্রতিস্থাপন করতে পারেন।

সম্ভবত এটি দ্রুততম নয়, তবে পারফরম্যান্স কোনও সমস্যা ছিল না বলে আমি এটিকে মার্জিত এবং বোধগম্য বলে মনে করেছি।

চিয়ার্স!


-2

আপনি একটি sedআদেশ দিয়ে এটি করতে পারেন :

 sed -e "
 s/[?()\[\]=+<>:;©®”,*|]/_/g
 s/"$'\t'"/ /g
 s/–/-/g
 s/\"/_/g
 s/[[:cntrl:]]/_/g"

আরও জটিল তবে সম্পর্কিত প্রশ্নটি এখানে দেখুন: stackoverflow.com/questions/4413427/…
DW

বাশের পরিবর্তে কেন সি # তে এটি করা দরকার? আমি এখন আসল প্রশ্নে সি # এর একটি ট্যাগ দেখছি, তবে কেন?
DW

4
আমি জানি, ঠিক আছে, কেন কেবল সি # অ্যাপ্লিকেশন থেকে বাশের কাছে অ্যাপ্লিকেশনটি শেল আউট করা যা এটি সম্পাদন করার জন্য ইনস্টল করা নাও হতে পারে?
পিটার রিচি 21
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.