सवाल "UTF-8 byte[] to string" आज भी प्रासंगिक क्यों है?
\n\nकल्पना करें: आपको नेटवर्क अनुरोध से बाइट्स की एक सरणी मिली, आपने एक बाइनरी फ़ाइल पढ़ी, या किसी API से डेटा डिसीरियलाइज़ किया। अंदर रूसी, अंग्रेजी या इमोजी में सामान्य टेक्स्ट है। लेकिन C# केवल byte[] देखता है। आपका काम इन शून्य और एक को एक समझने योग्य string में बदलना है।
यह आसान लगता है, है ना? एक मेथड कॉल और काम हो जाता है। लेकिन Stack Overflow पर सवाल "How to convert UTF-8 byte[] to string" हजारों बार देखा जाता है और इसके दर्जनों जवाब हैं। क्यों? क्योंकि शैतान विवरण में छिपा है: एन्कोडिंग, प्रदर्शन, सुरक्षा और अप्रत्याशित अपवाद।
\n\nइस लेख में हम सिर्फ तैयार कोड नहीं देंगे। हम दृष्टिकोणों की तुलना करेंगे, गति मापेंगे, छिपी समस्याओं पर चर्चा करेंगे और प्रत्येक कार्य के लिए सबसे अच्छा उपकरण चुनेंगे। यदि आप C# में लिखते हैं और नेटवर्क, फ़ाइलों या सीरियलाइज़ेशन के साथ काम करते हैं - यह सामग्री आपके लिए है।
\n\nसमस्या: byte[] एक स्ट्रिंग नहीं है
\n\nC# में, string UTF-16 एन्कोडिंग में संग्रहीत होती है। और आपको जो बाइट्स मिले हैं, वे संभवतः UTF-8 में एन्कोडेड हैं (इंटरनेट मानक, JSON, अधिकांश टेक्स्ट प्रोटोकॉल)। सीधा प्रकार रूपांतरण संभव नहीं है - कंपाइलर एक त्रुटि देगा।
एक डिकोडर की आवश्यकता है, जो UTF-8 बाइट्स के अनुक्रम को UTF-16 वर्णों में बदल दे। और यहाँ सबसे दिलचस्प शुरू होता है: डेवलपर के पास कम से कम तीन मौलिक रूप से भिन्न रास्ते हैं।
\n\nविधि 1: क्लासिक - Encoding.UTF8.GetString
\n\nMicrosoft द्वारा अनुशंसित सबसे स्पष्ट तरीका स्थैतिक वर्ग System.Text.Encoding का उपयोग करना है:
byte[] utf8Bytes = { 72, 101, 108, 108, 111, 32, 208, 191, 209, 128, 208, 176, 208, 178, 208, 176 }; // "Hello права"\nstring result = Encoding.UTF8.GetString(utf8Bytes);\nConsole.WriteLine(result); // आउटपुट: Hello права\n\nलाभ:
\n- \n
- सरलता - कोड की एक पंक्ति। \n
- UTF-8, UTF-16, ASCII, Latin-1 सहित सभी एन्कोडिंग का समर्थन। \n
- BOM (Byte Order Mark) का अंतर्निहित प्रबंधन - यदि सरणी की शुरुआत में UTF-8 मार्कर है, तो इसे अनदेखा कर दिया जाएगा। \n
- सुरक्षा - कोई
unsafeब्लॉक नहीं। \n
नुकसान:
\n- \n
- प्रत्येक कॉल एक नई स्ट्रिंग और एक आंतरिक बफर बनाता है। \n
- यदि बाइट्स दूषित हैं या अमान्य UTF-8 अनुक्रम हैं, तो विधि डिफ़ॉल्ट रूप से
DecoderFallbackExceptionफेंक देगी (यदि फ़ॉलबैक कॉन्फ़िगर नहीं किया गया है)। - बहुत बड़ी सरणियों (सैकड़ों मेगाबाइट) के लिए इष्टतम नहीं - डेटा की दोहरी प्रतिलिपि।
कब उपयोग करें?
\n95% मामलों में। यह उद्योग मानक है। यदि आप उच्च-लोड पार्सर नहीं लिख रहे हैं या गीगाबाइट लॉग के साथ काम नहीं कर रहे हैं - Encoding.UTF8.GetString का उपयोग करें।
विधि 2: तेज़ और खतरनाक - पॉइंटर्स के साथ unsafe
\n\nउन लोगों के लिए जो गति के पीछे भागते हैं और unsafe से नहीं डरते। विचार: हम जानते हैं कि UTF-8 और UTF-16 अलग-अलग एन्कोडिंग हैं, लेकिन यदि सरणी में केवल ASCII वर्ण (कोड 127 तक) हैं, तो प्रत्येक बाइट को बिना डिकोडिंग के 2-बाइट वर्ण में "खींचा" जा सकता है।
unsafe string UnsafeAsciiBytesToString(byte[] bytes)\n{\n fixed (byte* pBytes = bytes)\n {\n return new string((sbyte*)pBytes, 0, bytes.Length);\n }\n}\n\nयह कोड केवल ASCII के लिए काम करता है! रूसी टेक्स्ट (वर्ण > 127) के लिए, परिणाम बकवास होगा। लेकिन शुद्ध अंग्रेजी के लिए, यह Encoding.UTF8.GetString से 2-3 गुना तेज़ काम करता है।
लाभ:
\n- \n
- न्यूनतम ओवरहेड - कोई प्रतिलिपि नहीं, कोई डिकोडिंग नहीं।
- HTTP हेडर, JSON कुंजियों (यदि वे ASCII हैं) को पार्स करने के लिए आदर्श।
नुकसान:
\n- \n
- मल्टी-बाइट वर्णों के लिए खतरनाक - डेटा भ्रष्टाचार।
- प्रोजेक्ट में
unsafeअनुमति की आवश्यकता है (हर जगह अनुमति नहीं है)। - प्रोसेस नहीं करता