সি # তে স্ট্রিং ফাইল-পাথ নিরাপদ করার কোনও উপায় আছে কি?


94

আমার প্রোগ্রামটি ইন্টারনেট থেকে নির্বিচারে স্ট্রিং নেবে এবং সেগুলিকে ফাইলের নামের জন্য ব্যবহার করবে। এই স্ট্রিংগুলি থেকে খারাপ চরিত্রগুলি অপসারণ করার কোনও সহজ উপায় আছে বা এর জন্য আমার কোনও কাস্টম ফাংশন লিখতে হবে?


উত্তর:


172

ওহ, আমি যখন ঘৃণা করি তখন লোকেরা কোন অক্ষরগুলি বৈধ কিনা তা অনুমান করার চেষ্টা করে। সম্পূর্ণরূপে অ-বহনযোগ্য (সর্বদা মনো সম্পর্কে চিন্তাভাবনা করা) হওয়া ছাড়াও, পূর্ববর্তী উভয় মন্তব্যেই আরও 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

83
সি # সংস্করণ: ফরচ (পথের মধ্যে সি সি। গেটআইনডুয়েলফিলনেমচার্স ()) N ফাইলের নাম = ফাইলনাম.প্লেস (সি, '-'); }
jcollum

8
কীভাবে এই সমাধানটি নামগুলির দ্বন্দ্বগুলি পরিচালনা করবে? দেখে মনে হচ্ছে একাধিক স্ট্রিং একক ফাইলের নামের সাথে মিলে যেতে পারে (উদাহরণস্বরূপ "Hell" "এবং" Hell "")। আপনি যদি আপত্তিজনক অক্ষরগুলি অপসারণ করতে ঠিক থাকেন তবে জরিমানা; অন্যথায় আপনার নামের দ্বন্দ্বগুলি পরিচালনা করতে সাবধান হওয়া দরকার।
স্টেফানো রিকার্ডি

4
ফাইলাইটিমের নামের (এবং পথ) দৈর্ঘ্যের সীমা সম্পর্কে কী বলা যায়? সংরক্ষিত ফাইলের নামগুলি (পিআরএন কন) কী? আপনার যদি ডেটা এবং মূল নাম সংরক্ষণ করতে হয় তবে আপনি গাইডের নাম সহ 2 টি ফাইল ব্যবহার করতে পারেন: গাইড. টেক্সট এবং গাইড.ড্যাট
জ্যাক

7
এক লাইনার, মজাদার ফলাফলের জন্য = পথ .GetInuthorFileNameChars () Ag
পল নফ্ফ

4
@ পলকনোফ্ফ, আপনি কি নিশ্চিত যে জেটব্রেইনের সেই কোডটির কপিরাইট নেই;)
মার্কাস

37

অবৈধ অক্ষর ফেলা:

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

34

এই প্রশ্নের হয়েছে জিজ্ঞাসা অনেক বার সামনে এবং, যতবার নির্দিষ্ট আগে, IO.Path.GetInvalidFileNameCharsপর্যাপ্ত নয়।

প্রথমত, পিআরএন এবং সিওএন এর মতো অনেক নাম রয়েছে যা সংরক্ষিত রয়েছে এবং ফাইলের জন্য অনুমোদিত নয়। কেবলমাত্র মূল ফোল্ডারে অন্য নাম অনুমোদিত নয়। একটি সময়ের মধ্যে শেষ হওয়া নামগুলিও অনুমোদিত নয়।

দ্বিতীয়ত, দৈর্ঘ্যের বিভিন্ন সীমাবদ্ধতা রয়েছে। এনটিএফএসের জন্য সম্পূর্ণ তালিকাটি এখানে পড়ুন

তৃতীয়ত, আপনি অন্যান্য সীমাবদ্ধতা রয়েছে এমন ফাইল সিস্টেমে সংযুক্ত করতে পারেন। উদাহরণস্বরূপ, আইএসও 9660 ফাইলের নামগুলি "-" দিয়ে শুরু করতে পারে না তবে এটি ধারণ করতে পারে।

চতুর্থত, দুটি প্রক্রিয়া যদি "নির্বিচারে" একই নামটি গ্রহণ করে তবে আপনি কী করবেন?

সাধারণভাবে, ফাইলের নামের জন্য বাহ্যিকভাবে উত্পাদিত নাম ব্যবহার করা একটি খারাপ ধারণা। আমি আপনার নিজের ব্যক্তিগত ফাইলের নাম উত্পন্ন করার এবং মানব-পঠনযোগ্য নামগুলি অভ্যন্তরীণভাবে সংরক্ষণ করার পরামর্শ দিচ্ছি।


13
আপনি প্রযুক্তিগতভাবে সঠিক হলেও, getInuthorFileNameChars আপনি যে পরিস্থিতিতে এটি ব্যবহার করতে চান তার 80% এর জন্য ভাল is তাই এটি একটি উত্তম উত্তর। আমি মনে করি গ্রহণযোগ্য উত্তরের মন্তব্য হিসাবে আপনার উত্তরটি আরও উপযুক্ত হতে পারে।
কিউবানএক্স

4
আমি ডুরহাইআর্ক এর সাথে একমত নির্দেশিকা হিসাবে রেফারেন্স হিসাবে ফাইলটি অভ্যন্তরীণভাবে সংরক্ষণ করুন যা "বন্ধুত্বপূর্ণ নাম" এর বিরুদ্ধে যা একটি ডাটাবেজে সঞ্চিত থাকে। ব্যবহারকারীদের ওয়েবসাইটে আপনার পাথগুলি নিয়ন্ত্রণ করতে দেবেন না তারা আপনার ওয়েবকনফিগ চুরি করার চেষ্টা করবে। আপনি যদি এটি পরিষ্কার করার জন্য ইউআরএল পুনরায় রচনাটি অন্তর্ভুক্ত করেন তবে এটি কেবলমাত্র ডেটাবেজে মিলিত বন্ধুত্বপূর্ণ url এর জন্য কাজ করবে।
rtpHarry

22

আমি গ্রাওনওল্ফের সাথে একমত এবং এর সুপারিশ করব Path.GetInvalidFileNameChars()

এখানে আমার সি # অবদান:

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

পিএস - এটি হওয়া উচিত এর চেয়ে আরও গুপ্ত - আমি সংক্ষিপ্ত হওয়ার চেষ্টা করছিলাম।


4
বিশ্বে কেন আপনি Array.ForEachকেবল foreachএখানে পরিবর্তে ব্যবহার করবেন
ব্লুরাজা - ড্যানি ফ্লুঘুফুট

9
আপনি যদি আরও সংক্ষিপ্ত / ক্রিপ্টিক হতে চেয়েছিলেন:Path.GetInvalidFileNameChars().Aggregate(file, (current, c) => current.Replace(c, '-'))
মাইকেল পেতিটো

@ ব্লুরাজা-ড্যানিপ্লুঘুফুট কারণ আপনি এটিকে আরও ধীর করতে চান?
জোনাথন অ্যালেন

@ জোনাথন অ্যালেন, আপনি কী ভাবেন যে ভবিষ্যদ্বাণী অ্যারের চেয়ে দ্রুত?
রায়ান বুডিকোম

4
@rbuddicom অ্যারে। ফরইচ একটি প্রতিনিধি গ্রহণ করে, যার অর্থ এটি এমন কোনও ফাংশনটি আহ্বান করা দরকার যা অন্তর্ভুক্ত করা যায় না। সংক্ষিপ্ত স্ট্রিংয়ের জন্য, আপনি প্রকৃত যুক্তির চেয়ে ফাংশন কল ওভারহেডে বেশি সময় ব্যয় করতে পারেন। .NET কোর ওভারহেড হ্রাস করে কলগুলি "ডি-ভার্চুয়ালাইজ" করার উপায়গুলি দেখছে।
জোনাথন অ্যালেন

13

এখানে আমার সংস্করণ:

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

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

আমি বলি যে ডাব্লু / ও প্রোফাইলিং করছে - এটি আমার কাছে কেবল "অনুভূত" হয়েছে। :)


4
আপনি new HashSet<char>(Path.GetInvalidFileNameChars())ও (এন) গণনা এড়াতে করতে পারেন - মাইক্রো-অপ্টিমাইজেশন।
ট্রুউইল

12

আমি এখন যে ফাংশনটি ব্যবহার করছি তা এখানে রয়েছে (সি # উদাহরণের জন্য ধন্যবাদ জ্যাকলাম):

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

সুবিধার জন্য আমি এটি "সহায়ক" শ্রেণিতে রেখেছি।


7

আপনি যদি সমস্ত বিশেষ অক্ষরগুলি দ্রুত বের করতে চান যা কখনও কখনও ফাইলের নামের জন্য আরও বেশি ব্যবহারকারী পাঠযোগ্য হয় এটি দুর্দান্তভাবে কাজ করে:

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"

4
আসলে \Wঅ-আলফা-সংখ্যার ( [^A-Za-z0-9_]) এর চেয়ে বেশি মেলে । সমস্ত ইউনিকোড 'শব্দের' অক্ষর (русский 中文 ... ইত্যাদি) আর প্রতিস্থাপন করা হবে না। তবে এটি একটি ভাল জিনিস।
ইসমাইল 21

কেবলমাত্র খারাপ দিক এটি হ'ল এটি .আপনাকে সরিয়ে দেয় যাতে আপনাকে প্রথমে এক্সটেনশানটি বের করতে হবে এবং পরে এটি আবার যুক্ত করতে হবে।
অবাক

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

5

স্ট্রিংটিকে বেস বেসের সমতুল্যে কেন রূপান্তর করবেন না:

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

আপনি যদি এটিকে আবার রূপান্তর করতে চান তবে আপনি এটি পড়তে পারেন:

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

আমি এলোমেলো বর্ণনা থেকে অনন্য নামের পিএনজি ফাইলগুলি সংরক্ষণ করতে এটি ব্যবহার করেছি।


5

ক্লোরপ্লেয়ারের ( http://github.com/Zoomicon/ClipFlair ) স্ট্রিংএক্সটেনশনগুলি স্ট্যাটিক ক্লাস (ইউটিলেস.সিলভারলাইট প্রজেক্ট) উপরের ডোর হাই আর্ক দ্বারা পোস্ট করা সম্পর্কিত স্ট্যাকওভারফ্লো প্রশ্নগুলির লিঙ্কগুলি থেকে প্রাপ্ত তথ্যের উপর ভিত্তি করে আমি এখানে যা যুক্ত করেছি তা এখানে :

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

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

1

আমি এটি দ্রুত এবং সহজে বুঝতে সহজ হিসাবে ব্যবহার করে দেখতে পেলাম:

<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অ্যারের।


1

আমার পুরানো প্রকল্পগুলি থেকে, আমি এই সমাধানটি পেয়েছি, যা 2 বছর ধরে নিখুঁতভাবে কাজ করছে। আমি অবৈধ অক্ষরগুলিকে "!" দিয়ে প্রতিস্থাপন করছি, এবং তারপরে দ্বিগুণ !! আপনার নিজের চর ব্যবহার করুন use

    public string GetSafeFilename(string filename)
    {
        string res = string.Join("!", filename.Split(Path.GetInvalidFileNameChars()));

        while (res.IndexOf("!!") >= 0)
            res = res.Replace("!!", "!");

        return res;
    }

0

অনেক অ্যানভার ব্যবহার করার পরামর্শ দেয় Path.GetInvalidFileNameChars()যা আমার কাছে খারাপ সমাধান বলে মনে হয়। আমি আপনাকে ব্ল্যাকলিস্টিংয়ের পরিবর্তে হোয়াইটলিস্টিং ব্যবহার করতে উত্সাহিত করি কারণ হ্যাকাররা সর্বদা এটিকে বাইপাস করার জন্য সর্বদা উপায় খুঁজে পাবে।

আপনি যে কোডটি ব্যবহার করতে পারেন তার উদাহরণ এখানে রয়েছে:

    string whitelist = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.";
    foreach (char c in filename)
    {
        if (!whitelist.Contains(c))
        {
            filename = filename.Replace(c, '-');
        }
    }
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.