खोज…


टिप्पणियों

.NET स्ट्रिंग्स में System.String वर्णों का अनुक्रम है। System.Char , प्रत्येक वर्ण UTF-16 एन्कोडेड कोड-यूनिट है। यह भेद महत्वपूर्ण है क्योंकि बोले जाने वाली भाषा की परिभाषा चरित्र की है और .NET (और कई अन्य भाषा) चरित्र की परिभाषा अलग है।

एक वर्ण , जिसे सही ढंग से ग्रेपमे कहा जाना चाहिए, इसे ग्लिफ़ के रूप में प्रदर्शित किया जाता है और इसे एक या अधिक यूनिकोड कोड-पॉइंट द्वारा परिभाषित किया जाता है । प्रत्येक कोड-पॉइंट को कोड-यूनिट के अनुक्रम में एन्कोड किया गया है। अब यह स्पष्ट होना चाहिए कि क्यों एक एकल System.Char हमेशा एक अंगूर का प्रतिनिधित्व नहीं करता है, आइए वास्तविक दुनिया में देखें कि वे कैसे अलग हैं:

  • वर्णों के संयोजन के कारण, एक अंगूर, दो या अधिक कोड-बिंदुओं के परिणामस्वरूप हो सकता है: à दो कोड-बिंदुओं से बना होता है: U + 0061 LATIN SMALL LETTER A और U + 0300 COMBINING GRAVE ACCENT । यह सबसे आम गलती है क्योंकि "à".Length == 2 जबकि आप 1 उम्मीद कर सकते हैं।
  • दोहराया अक्षर, कर रहे हैं उदाहरण के लिए एक एक एकल कोड सूत्री U + 00E0 लैटिन छोटे अक्षर एक साथ कब्र या दो कोड-अंक जैसा कि ऊपर बताया हो सकता है के लिए। स्पष्ट रूप से उन्हें एक ही तुलना करनी चाहिए: "\u00e0" == "\u0061\u0300" (भले ही "\u00e0".Length != "\u0061\u0300".Length )। स्ट्रिंग स्ट्रिंग द्वारा किए गए सामान्यीकरण के कारण यह संभव है। सामान्यीकृत String.Normalize() विधि।
  • एक यूनिकोड अनुक्रम उदाहरण चरित्र U + D55C हान चरित्र के लिए, एक बना या विघटित अनुक्रम हो सकती है एक भी कोड सूत्री (UTF-16 में एक भी कोड इकाई के रूप में एन्कोड) या उसके अक्षरों का एक विघटित अनुक्रम हो सकता है ᄒ, और उनकी बराबरी की जानी चाहिए।
  • एक कोड-पॉइंट को एक से अधिक कोड-इकाइयों में एन्कोड किया जा सकता है: चरित्र 𠂊 U + 2008A HAN CHARACTER को दो System.Char ( "\ud840\udc8a" ) के रूप में एन्कोड किया गया है, भले ही यह केवल एक कोड-पॉइंट हो: UTF-16 एन्कोडिंग निश्चित आकार नहीं है! यह अनगिनत बग (गंभीर सुरक्षा कीड़े भी) का एक स्रोत है, उदाहरण के लिए यदि आपका आवेदन एक अधिकतम लंबाई लागू करता है और उस पर नेत्रहीन रूप से स्ट्रिंग काटता है तो आप एक अमान्य स्ट्रिंग बना सकते हैं।
  • कुछ भाषाओं में है संयुक्ताक्षर फिर जब आप Chemie से पहले fyzika होगा स्ट्रिंग की एक सूची आदेश देने चेक में उदाहरण ch एक स्टैंडअलोन पत्र (ज के बाद है के लिए और मैं पहले, और trigraphs।

पाठ से निपटने के बारे में बहुत अधिक मुद्दे हैं, उदाहरण के लिए देखें कि मैं चरित्र की तुलना द्वारा यूनिकोड जागरूक चरित्र का प्रदर्शन कैसे कर सकता हूं? एक व्यापक परिचय और संबंधित तर्कों के लिए अधिक लिंक के लिए।

सामान्य तौर पर जब अंतरराष्ट्रीय पाठ से निपटने के लिए आप इस सरल फ़ंक्शन का उपयोग एक स्ट्रिंग में पाठ तत्वों की गणना करने के लिए कर सकते हैं (यूनिकोड सरोगेट्स और एन्कोडिंग को तोड़ने से बचें):

public static class StringExtensions
{
    public static IEnumerable<string> EnumerateCharacters(this string s)
    {
        if (s == null)
            return Enumerable.Empty<string>();

        var enumerator = StringInfo.GetTextElementEnumerator(s.Normalize());
        while (enumerator.MoveNext())
            yield return (string)enumerator.Value;
    }
}

अलग-अलग वर्णों की गणना करें

यदि आपको अलग-अलग वर्णों की गणना करने की आवश्यकता है, तो रिमार्क्स अनुभाग में बताए गए कारणों के लिए, आप बस Length संपत्ति का उपयोग नहीं कर सकते हैं क्योंकि यह System.Char की सरणी की लंबाई है जो वर्ण नहीं हैं, लेकिन कोड-इकाइयां (यूनिकोड कोड-पॉइंट नहीं हैं न ही अंगूर)। यदि, उदाहरण के लिए, आप केवल text.Distinct().Count() लिखते हैं। text.Distinct().Count() आपको गलत परिणाम, सही कोड मिलेगा:

int distinctCharactersCount = text.EnumerateCharacters().Count();

एक कदम आगे प्रत्येक चरित्र की घटनाओं को गिनना है , यदि प्रदर्शन कोई समस्या नहीं है तो आप इसे बस इस तरह से कर सकते हैं (इस उदाहरण में मामले की परवाह किए बिना):

var frequencies = text.EnumerateCharacters()
    .GroupBy(x => x, StringComparer.CurrentCultureIgnoreCase)
    .Select(x => new { Character = x.Key, Count = x.Count() };

गिनती के अक्षर

यदि आपको वर्णों की गणना करने की आवश्यकता है, तो रिमार्क्स अनुभाग में बताए गए कारणों के लिए, आप केवल लंबाई की संपत्ति का उपयोग नहीं कर सकते क्योंकि यह System.Char की सरणी की लंबाई है जो वर्ण नहीं हैं, लेकिन कोड-इकाइयां (यूनिकोड कोड-पॉइंट नहीं हैं graphemes)। सही कोड है:

int length = text.EnumerateCharacters().Count();

एक छोटा अनुकूलन विशेष रूप से इस उद्देश्य के लिए EnumerateCharacters() विस्तार विधि को फिर से लिख सकता है:

public static class StringExtensions
{
    public static int CountCharacters(this string text)
    {
        if (String.IsNullOrEmpty(text))
            return 0;

        int count = 0;
        var enumerator = StringInfo.GetTextElementEnumerator(text);
        while (enumerator.MoveNext())
            ++count;

        return count;
    }
}

एक चरित्र की घटनाओं की गणना

रिमार्क्स अनुभाग में बताए गए कारणों के कारण आप ऐसा नहीं कर सकते (जब तक कि आप किसी विशिष्ट कोड-यूनिट की घटनाओं को गिनना नहीं चाहते):

int count = text.Count(x => x == ch);

आपको अधिक जटिल फ़ंक्शन की आवश्यकता है:

public static int CountOccurrencesOf(this string text, string character)
{
    return text.EnumerateCharacters()
        .Count(x => String.Equals(x, character, StringComparer.CurrentCulture));
}

ध्यान दें कि स्ट्रिंग तुलना (चरित्र तुलना के विपरीत जो कि संस्कृति अपरिवर्तनीय है) को हमेशा एक विशिष्ट संस्कृति के नियमों के अनुसार किया जाना चाहिए।

निश्चित लंबाई के ब्लॉक में स्ट्रिंग विभाजित करें

हम एक स्ट्रिंग को मनमाने ढंग से नहीं तोड़ सकते (क्योंकि एक System.Char अकेले मान्य नहीं हो सकता है क्योंकि यह एक संयोजन चरित्र या सरोगेट का हिस्सा है) तो कोड को ध्यान में रखना चाहिए (ध्यान दें कि लंबाई के साथ मेरा मतलब है कि अंगूरों की संख्या नहीं है कोड-इकाइयों की संख्या):

public static IEnumerable<string> Split(this string value, int desiredLength)
{
    var characters = StringInfo.GetTextElementEnumerator(value);
    while (characters.MoveNext())
        yield return String.Concat(Take(characters, desiredLength));
}

private static IEnumerable<string> Take(TextElementEnumerator enumerator, int count)
{
    for (int i = 0; i < count; ++i)
    {
        yield return (string)enumerator.Current;

        if (!enumerator.MoveNext())
            yield break;
    }
}

एक और एन्कोडिंग से स्ट्रिंग को / में बदलें

.NET स्ट्रिंग्स में System.Char (UTF-16 कोड-इकाइयां) शामिल हैं। यदि आप किसी अन्य एन्कोडिंग के साथ टेक्स्ट को सहेजना (या प्रबंधित) करना चाहते हैं, तो आपको System.Byte की एक सरणी के साथ काम करना होगा।

रूपांतरण से व्युत्पन्न वर्ग द्वारा किया जाता है System.Text.Encoder और System.Text.Decoder जो, एक साथ, / के लिए एक और एन्कोडिंग से एक बाइट एक्स इनकोडिंग सरणी से परिवर्तित कर सकते हैं ( byte[] एक UTF-16 इनकोडिंग को System.String और उपाध्यक्ष -versa)।

क्योंकि एनकोडर / डिकोडर आम तौर पर एक दूसरे के बहुत करीब काम करते हैं, जिन्हें वे System.Text.Encoding से व्युत्पन्न वर्ग में एक साथ समूहीकृत करते हैं, व्युत्पन्न वर्ग लोकप्रिय एन्कोडिंग / (UTF-8, UTF-16 और इसी तरह) से रूपांतरण प्रदान करते हैं।

उदाहरण:

एक स्ट्रिंग को UTF-8 में बदलें

byte[] data = Encoding.UTF8.GetBytes("This is my text");

UTF-8 डेटा को एक स्ट्रिंग में बदलें

var text = Encoding.UTF8.GetString(data);

मौजूदा टेक्स्ट फ़ाइल की एन्कोडिंग बदलें

यह कोड एक UTF-8 एन्कोडेड टेक्स्ट फ़ाइल की सामग्री को पढ़ेगा और इसे UTF-16 के रूप में एन्कोडेड वापस बचाएगा। ध्यान दें कि यदि फ़ाइल बड़ी है तो यह कोड इष्टतम नहीं है क्योंकि यह मेमोरी में इसकी सभी सामग्री को पढ़ेगी:

var content = File.ReadAllText(path, Encoding.UTF8);
File.WriteAllText(content, Encoding.UTF16);

Object.ToString () वर्चुअल विधि

.NET में सब कुछ एक वस्तु है, इसलिए हर प्रकार की गई है ToString() विधि में परिभाषित Object वर्ग जो अधिरोहित जा सकता है। इस पद्धति का डिफ़ॉल्ट कार्यान्वयन केवल प्रकार का नाम लौटाता है:

public class Foo
{
}

var foo = new Foo();
Console.WriteLine(foo); // outputs Foo

स्ट्रिंग के साथ मान को बदलते समय ToString() को संक्षेप में कहा जाता है:

public class Foo
{
    public override string ToString()
    {
        return "I am Foo";
    }
}

var foo = new Foo();
Console.WriteLine("I am bar and "+foo);// outputs I am bar and I am Foo

इस विधि का परिणाम भी डीबगिंग टूल द्वारा बड़े पैमाने पर उपयोग किया जाता है। यदि, किसी कारण से, आप इस विधि को ओवरराइड नहीं करना चाहते हैं, लेकिन यह डिबग करना चाहते हैं कि डिबगर आपके प्रकार का मान कैसे दिखाता है, तो डिबगरडिसप्ले एट्रीब्यूट ( MSDN ) का उपयोग करें:

// [DebuggerDisplay("Person = FN {FirstName}, LN {LastName}")]
[DebuggerDisplay("Person = FN {"+nameof(Person.FirstName)+"}, LN {"+nameof(Person.LastName)+"}")]
public class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set;}
    // ...
}

तार की अपरिवर्तनीयता

तार अपरिवर्तनीय हैं। आप अभी मौजूदा स्ट्रिंग नहीं बदल सकते। स्ट्रिंग के किसी भी ऑपरेशन में नए मूल्य वाले स्ट्रिंग की एक नई आवृत्ति उत्पन्न होती है। इसका मतलब है कि यदि आपको एक एकल चरित्र को बहुत लंबे स्ट्रिंग में बदलने की आवश्यकता है, तो स्मृति को एक नए मूल्य के लिए आवंटित किया जाएगा।

string veryLongString = ...
// memory is allocated
string newString = veryLongString.Remove(0,1); // removes first character of the string.

यदि आपको स्ट्रिंग मान के साथ कई ऑपरेशन करने की आवश्यकता है, तो StringBuilder वर्ग का उपयोग करें जो कुशल स्ट्रिंग्स हेरफेर के लिए डिज़ाइन किया गया है:

var sb = new StringBuilder(someInitialString);
foreach(var str in manyManyStrings)
{
    sb.Append(str);
} 
var finalString = sb.ToString();

Сomparing तार

String एक संदर्भ प्रकार होने के बावजूद == ऑपरेटर संदर्भों के बजाय स्ट्रिंग मानों की तुलना करता है।

जैसा कि आप जानते हैं कि string केवल वर्णों की एक सरणी है। लेकिन अगर आपको लगता है कि तार की समानता की जाँच और तुलना चरित्र द्वारा की जाती है, तो आप गलत हैं। यह ऑपरेशन संस्कृति विशिष्ट है (नीचे टिप्पणी देखें): कुछ वर्ण अनुक्रमों को संस्कृति के आधार पर समान माना जा सकता है।

दो स्ट्रिंग्स की Length गुणों की तुलना करके शॉर्ट सर्किटिंग समानता जांच से पहले दो बार सोचें!

यदि आप डिफ़ॉल्ट व्यवहार को बदलने की आवश्यकता है, तो String.Equals पद्धति के अधिभार का उपयोग करें जो अतिरिक्त StringComparison गणन मान को स्वीकार करता है।



Modified text is an extract of the original Stack Overflow Documentation
के तहत लाइसेंस प्राप्त है CC BY-SA 3.0
से संबद्ध नहीं है Stack Overflow