সি # ফাইলের নাম স্যানিটাইজ করুন


174

আমি সম্প্রতি বিভিন্ন লোকেশন থেকে এমপি 3 গুলির একটি গুচ্ছকে একটি ভান্ডারে পরিণত করছি। আমি আইডি 3 ট্যাগ ব্যবহার করে নতুন ফাইলের নামগুলি তৈরি করছিলাম (ধন্যবাদ, ট্যাগলিব-শার্প!) এবং আমি লক্ষ্য করেছি যে আমি একটি পেয়ে যাচ্ছি System.NotSupportedException:

"প্রদত্ত পথের বিন্যাসটি সমর্থিত নয়।"

এটি হয় File.Copy()বা দ্বারা উত্পাদিত হয়েছিল Directory.CreateDirectory()

আমার ফাইলের নাম স্যানিটাইজ করা দরকার তা বুঝতে সময় লাগেনি। সুতরাং আমি স্পষ্টতই কাজটি করেছি:

public static string SanitizePath_(string path, char replaceChar)
{
    string dir = Path.GetDirectoryName(path);
    foreach (char c in Path.GetInvalidPathChars())
        dir = dir.Replace(c, replaceChar);

    string name = Path.GetFileName(path);
    foreach (char c in Path.GetInvalidFileNameChars())
        name = name.Replace(c, replaceChar);

    return dir + name;
}

আমার অবাক করে দিয়েছি, আমি ব্যতিক্রম পেতে থাকি। দেখা গেছে যে ':' এর সেটে নেই Path.GetInvalidPathChars(), কারণ এটি কোনও মূলের রুটে বৈধ। আমি মনে করি এটি উপলব্ধি করে - তবে এটি একটি সাধারণ সমস্যা হতে হবে। কারও কি এমন কিছু সংক্ষিপ্ত কোড রয়েছে যা একটি পথ স্যানিটাইজ করে? সর্বাধিক বিশদ আমি এটি নিয়ে এসেছি, তবে মনে হচ্ছে এটি সম্ভবত অতিরিক্ত ওভারকিল।

    // replaces invalid characters with replaceChar
    public static string SanitizePath(string path, char replaceChar)
    {
        // construct a list of characters that can't show up in filenames.
        // need to do this because ":" is not in InvalidPathChars
        if (_BadChars == null)
        {
            _BadChars = new List<char>(Path.GetInvalidFileNameChars());
            _BadChars.AddRange(Path.GetInvalidPathChars());
            _BadChars = Utility.GetUnique<char>(_BadChars);
        }

        // remove root
        string root = Path.GetPathRoot(path);
        path = path.Remove(0, root.Length);

        // split on the directory separator character. Need to do this
        // because the separator is not valid in a filename.
        List<string> parts = new List<string>(path.Split(new char[]{Path.DirectorySeparatorChar}));

        // check each part to make sure it is valid.
        for (int i = 0; i < parts.Count; i++)
        {
            string part = parts[i];
            foreach (char c in _BadChars)
            {
                part = part.Replace(c, replaceChar);
            }
            parts[i] = part;
        }

        return root + Utility.Join(parts, Path.DirectorySeparatorChar.ToString());
    }

এই ফাংশনটি দ্রুত এবং কম বারোক তৈরির জন্য যে কোনও উন্নতি করা হয়েছে তা প্রশংসিত হবে।


উত্তর:


314

কোনও ফাইলের নাম পরিষ্কার করতে আপনি এটি করতে পারেন could

private static string MakeValidFileName( string name )
{
   string invalidChars = System.Text.RegularExpressions.Regex.Escape( new string( System.IO.Path.GetInvalidFileNameChars() ) );
   string invalidRegStr = string.Format( @"([{0}]*\.+$)|([{0}]+)", invalidChars );

   return System.Text.RegularExpressions.Regex.Replace( name, invalidRegStr, "_" );
}

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

15
সম্ভবত, তবে এই কোডটি অবশ্যই আমাকে সহায়তা করেছিল যখন আমার একই সমস্যা হয়েছিল :)
এমএমআর

8
এবং আর একটি সম্ভাব্য দুর্দান্ত এসও ব্যবহারকারী হাঁটছেন ... এই ফাংশনটি দুর্দান্ত। ধন্যবাদ আদ্রেভডিএম ...
ড্যান রোজেনস্টার্ক

19
দুর্দান্ত পদ্ধতি। সংরক্ষিত শব্দগুলি এখনও আপনাকে দংশন করবে এবং আপনার মাথা আঁচড়ে যাবে forget উত্স: উইকিপিডিয়া ফাইলের নাম সংরক্ষিত শব্দ
স্পড

8
পিরিয়ডগুলি অবৈধ অক্ষর হয় যদি তারা ফাইলের নামের শেষে থাকে তবে এগুলি GetInvalidFileNameCharsঅন্তর্ভুক্ত করে না। এটি উইন্ডোগুলিতে কোনও ব্যতিক্রম ছুঁড়ে না, এটি কেবল তাদের সরিয়ে দেয়, তবে আপনি যদি সময়কালটি আশা করেন তবে এটি অপ্রত্যাশিত আচরণের কারণ হতে পারে। আমি .স্ট্রিংয়ের শেষে থাকলে অবৈধ অক্ষরের একটি হিসাবে বিবেচিত হওয়ার জন্য কেসটি হ্যান্ডেল করার জন্য আমি রেজেক্সকে সংশোধন করেছি ।
স্কট চেম্বারলাইন

120

একটি সংক্ষিপ্ত সমাধান:

var invalids = System.IO.Path.GetInvalidFileNameChars();
var newName = String.Join("_", origFileName.Split(invalids, StringSplitOptions.RemoveEmptyEntries) ).TrimEnd('.');

1
@ পিটারমজিদ: টিআইএল যে লাইন গণনা শূন্য থেকে শুরু হবে :-)
গ্যারি ম্যাকগিল

এটি শীর্ষস্থানীয় উত্তরের চেয়ে বিশেষত ASP.NET কোরের থেকে ভাল যা প্ল্যাটফর্মের উপর ভিত্তি করে বিভিন্ন চরিত্রগুলি ফিরিয়ে দিতে পারে।
আলেক্সি

79

আন্দ্রের দুর্দান্ত উত্তরের ভিত্তিতে কিন্তু সংরক্ষিত শব্দের বিষয়ে স্পডের মন্তব্যটি আমলে নিয়ে আমি এই সংস্করণটি তৈরি করেছি:

/// <summary>
/// Strip illegal chars and reserved words from a candidate filename (should not include the directory path)
/// </summary>
/// <remarks>
/// http://stackoverflow.com/questions/309485/c-sharp-sanitize-file-name
/// </remarks>
public static string CoerceValidFileName(string filename)
{
    var invalidChars = Regex.Escape(new string(Path.GetInvalidFileNameChars()));
    var invalidReStr = string.Format(@"[{0}]+", invalidChars);

    var reservedWords = new []
    {
        "CON", "PRN", "AUX", "CLOCK$", "NUL", "COM0", "COM1", "COM2", "COM3", "COM4",
        "COM5", "COM6", "COM7", "COM8", "COM9", "LPT0", "LPT1", "LPT2", "LPT3", "LPT4",
        "LPT5", "LPT6", "LPT7", "LPT8", "LPT9"
    };

    var sanitisedNamePart = Regex.Replace(filename, invalidReStr, "_");
    foreach (var reservedWord in reservedWords)
    {
        var reservedWordPattern = string.Format("^{0}\\.", reservedWord);
        sanitisedNamePart = Regex.Replace(sanitisedNamePart, reservedWordPattern, "_reservedWord_.", RegexOptions.IgnoreCase);
    }

    return sanitisedNamePart;
}

এবং এগুলি আমার ইউনিট পরীক্ষা

[Test]
public void CoerceValidFileName_SimpleValid()
{
    var filename = @"thisIsValid.txt";
    var result = PathHelper.CoerceValidFileName(filename);
    Assert.AreEqual(filename, result);
}

[Test]
public void CoerceValidFileName_SimpleInvalid()
{
    var filename = @"thisIsNotValid\3\\_3.txt";
    var result = PathHelper.CoerceValidFileName(filename);
    Assert.AreEqual("thisIsNotValid_3__3.txt", result);
}

[Test]
public void CoerceValidFileName_InvalidExtension()
{
    var filename = @"thisIsNotValid.t\xt";
    var result = PathHelper.CoerceValidFileName(filename);
    Assert.AreEqual("thisIsNotValid.t_xt", result);
}

[Test]
public void CoerceValidFileName_KeywordInvalid()
{
    var filename = "aUx.txt";
    var result = PathHelper.CoerceValidFileName(filename);
    Assert.AreEqual("_reservedWord_.txt", result);
}

[Test]
public void CoerceValidFileName_KeywordValid()
{
    var filename = "auxillary.txt";
    var result = PathHelper.CoerceValidFileName(filename);
    Assert.AreEqual("auxillary.txt", result);
}

1
এটি একটি সম্পূর্ণ সম্পূর্ণ উত্তর, কমপক্ষে প্রশ্নের ফাইলনাম অংশে, এবং আরও উন্নয়নের দাবিদার।
ব্রায়ান ম্যাককে

2
গৌণ পরামর্শটি যেহেতু দেখে মনে হচ্ছে পদ্ধতিটি এই দিকে চলেছে: একটি কীওয়ার্ড যুক্ত করুন এটি একটি কার্যকর এক্সটেনশন পদ্ধতিতে পরিণত হয়। পাবলিক স্ট্যাটিক স্ট্রিং কোরেসিডভালিড ফাইলনেম (এই স্ট্রিং ফাইলের নাম)
রায়ান ম্যাকআর্থার

2
ছোট ত্রুটি: এই পদ্ধতিটি ফাইল এক্সটেনশন (উদা। COM1) ছাড়াই সংরক্ষিত শব্দগুলিকে পরিবর্তন করে না , যা নিষিদ্ধ রয়েছে। প্রস্তাবিত "^{0}(\\.|$)""_reservedWord_$1"
ফিক্সটি হ'ল

31
string clean = String.Concat(dirty.Split(Path.GetInvalidFileNameChars()));

5
এর String.Concat(dirty...)পরিবর্তে বিবেচনা করুনJoin(String.Empty...
ড্রাগজাস

DenNukem ইতিমধ্যে এই উত্তরটি প্রস্তাব করেছে: stackoverflow.com/a/13617375/244916 (যদিও মন্তব্যটি বিবেচনা করুন)।
ডুড পাস্কালো

4

আমি System.IO.Path.GetInvalidFileNameChars() অবৈধ অক্ষরগুলি পরীক্ষা করতে পদ্ধতিটি ব্যবহার করছি এবং আমার কোনও সমস্যা হয়নি।

আমি নিম্নলিখিত কোড ব্যবহার করছি:

foreach( char invalidchar in System.IO.Path.GetInvalidFileNameChars())
{
    filename = filename.Replace(invalidchar, '_');
}

3

আমি চরিত্রগুলি কোনও উপায়ে ধরে রাখতে চেয়েছি, কেবল কেবল চরিত্রটিকে একটি আন্ডারস্কোর দিয়ে প্রতিস্থাপন করতে পারি না।

আমি ভেবেছিলাম একটি উপায় হ'ল চরিত্রগুলিকে অনুরূপ বর্ণচিহ্নগুলির সাথে প্রতিস্থাপন করা (যা আমার পরিস্থিতিতে) নিয়মিত অক্ষর হিসাবে ব্যবহার করার সম্ভাবনা নেই। তাই আমি অবৈধ চরিত্রগুলির তালিকা নিয়েছি এবং পছন্দ মতো দেখতে পেয়েছি।

নীচেরগুলি লক-এ-পছন্দগুলির সাথে এনকোড এবং ডিকোড করার ফাংশন রয়েছে।

এই কোডটিতে সমস্ত System.IO.Path.GetInuthorFileNameChars () অক্ষরগুলির জন্য একটি সম্পূর্ণ তালিকা অন্তর্ভুক্ত নয়। সুতরাং যে কোনও অবশিষ্ট অক্ষরের জন্য আন্ডারস্কোর প্রতিস্থাপনটি প্রসারিত বা ব্যবহার করা আপনার পক্ষে।

private static Dictionary<string, string> EncodeMapping()
{
    //-- Following characters are invalid for windows file and folder names.
    //-- \/:*?"<>|
    Dictionary<string, string> dic = new Dictionary<string, string>();
    dic.Add(@"\", "Ì"); // U+OOCC
    dic.Add("/", "Í"); // U+OOCD
    dic.Add(":", "¦"); // U+00A6
    dic.Add("*", "¤"); // U+00A4
    dic.Add("?", "¿"); // U+00BF
    dic.Add(@"""", "ˮ"); // U+02EE
    dic.Add("<", "«"); // U+00AB
    dic.Add(">", "»"); // U+00BB
    dic.Add("|", "│"); // U+2502
    return dic;
}

public static string Escape(string name)
{
    foreach (KeyValuePair<string, string> replace in EncodeMapping())
    {
        name = name.Replace(replace.Key, replace.Value);
    }

    //-- handle dot at the end
    if (name.EndsWith(".")) name = name.CropRight(1) + "°";

    return name;
}

public static string UnEscape(string name)
{
    foreach (KeyValuePair<string, string> replace in EncodeMapping())
    {
        name = name.Replace(replace.Value, replace.Key);
    }

    //-- handle dot at the end
    if (name.EndsWith("°")) name = name.CropRight(1) + ".";

    return name;
}

আপনি নিজের পছন্দ মতো পছন্দ বেছে নিতে পারেন। আমি খনি নির্বাচন করতে উইন্ডোগুলিতে অক্ষর মানচিত্র অ্যাপ্লিকেশন ব্যবহার করেছি%windir%\system32\charmap.exe

আমি আবিষ্কারের মাধ্যমে সামঞ্জস্য করার সাথে সাথে আমি এই কোডটি আপডেট করব।


নোট অনেক অক্ষর আছে যা, আরো অনুরূপ চেহারা মত আছে পূর্ণচওড়া ফর্ম !"#$%&'()*+,-./:;<=>?@{|}~ বা মত তাদের অন্যান্য ধরনের /SOLIDUS এবং `/` ভগ্নাংশ SLASH যে ছাড়া সমস্যা ফাইলের নামের সরাসরি ব্যবহার করা যেতে পারে
phuclv

2

আমি মনে করি সমস্যাটি হ'ল আপনি প্রথমে Path.GetDirectoryNameখারাপ স্ট্রিংটিতে কল করুন। এটিতে যদি ফাইল-নামবিহীন অক্ষর থাকে তবে। নেট স্ট্রিংয়ের কোন অংশটি ডিরেক্টরি এবং নিক্ষেপ করা হয় তা বলতে পারে না। আপনাকে স্ট্রিং তুলনা করতে হবে।

ধরে নিলে এটি কেবল ফাইলের নামই খারাপ, পুরো পথটি নয়, এটি চেষ্টা করে দেখুন:

public static string SanitizePath(string path, char replaceChar)
{
    int filenamePos = path.LastIndexOf(Path.DirectorySeparatorChar) + 1;
    var sb = new System.Text.StringBuilder();
    sb.Append(path.Substring(0, filenamePos));
    for (int i = filenamePos; i < path.Length; i++)
    {
        char filenameChar = path[i];
        foreach (char c in Path.GetInvalidFileNameChars())
            if (filenameChar.Equals(c))
            {
                filenameChar = replaceChar;
                break;
            }

        sb.Append(filenameChar);
    }

    return sb.ToString();
}

2

অতীতে এর সাথে আমি সাফল্য পেয়েছি।

সুন্দর, সংক্ষিপ্ত এবং স্থির :-)

    public static string returnSafeString(string s)
    {
        foreach (char character in Path.GetInvalidFileNameChars())
        {
            s = s.Replace(character.ToString(),string.Empty);
        }

        foreach (char character in Path.GetInvalidPathChars())
        {
            s = s.Replace(character.ToString(), string.Empty);
        }

        return (s);
    }

2

এখানে অনেকগুলি কাজের সমাধান রয়েছে। কেবলমাত্র সম্পূর্ণতার জন্য, এখানে এমন একটি পদ্ধতির কথা বলা হয়েছে যা রেইগেক্স ব্যবহার করে না, তবে লিনকিউ ব্যবহার করে:

var invalids = Path.GetInvalidFileNameChars();
filename = invalids.Aggregate(filename, (current, c) => current.Replace(c, '_'));

এছাড়াও, এটি একটি খুব সংক্ষিপ্ত সমাধান;)


1
আমি একটি লাইনার পছন্দ করি :)
ল্যারি

1

আন্দ্রে কোডের ভিত্তিতে এখানে একটি দক্ষ অলস লোডিং এক্সটেনশন পদ্ধতি রয়েছে:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace LT
{
    public static class Utility
    {
        static string invalidRegStr;

        public static string MakeValidFileName(this string name)
        {
            if (invalidRegStr == null)
            {
                var invalidChars = System.Text.RegularExpressions.Regex.Escape(new string(System.IO.Path.GetInvalidFileNameChars()));
                invalidRegStr = string.Format(@"([{0}]*\.+$)|([{0}]+)", invalidChars);
            }

            return System.Text.RegularExpressions.Regex.Replace(name, invalidRegStr, "_");
        }
    }
}

0

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


-1
using System;
using System.IO;
using System.Linq;
using System.Text;

public class Program
{
    public static void Main()
    {
        try
        {
            var badString = "ABC\\DEF/GHI<JKL>MNO:PQR\"STU\tVWX|YZA*BCD?EFG";
            Console.WriteLine(badString);
            Console.WriteLine(SanitizeFileName(badString, '.'));
            Console.WriteLine(SanitizeFileName(badString));
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.ToString());
        }
    }

    private static string SanitizeFileName(string fileName, char? replacement = null)
    {
        if (fileName == null) { return null; }
        if (fileName.Length == 0) { return ""; }

        var sb = new StringBuilder();
        var badChars = Path.GetInvalidFileNameChars().ToList();

        foreach (var @char in fileName)
        {
            if (badChars.Contains(@char)) 
            {
                if (replacement.HasValue)
                {
                    sb.Append(replacement.Value);
                }
                continue; 
            }
            sb.Append(@char);
        }
        return sb.ToString();
    }
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.