C # में बाइट सरणी में परिवर्तित स्ट्रिंग


670

मैं VB से C # में कुछ परिवर्तित कर रहा हूं। इस कथन के वाक्य विन्यास के साथ एक समस्या है:

if ((searchResult.Properties["user"].Count > 0))
{
    profile.User = System.Text.Encoding.UTF8.GetString(searchResult.Properties["user"][0]);
}

मैं तब निम्न त्रुटियाँ देखता हूँ:

तर्क 1: 'ऑब्जेक्ट' से 'बाइट []' में परिवर्तित नहीं हो सकता

'System.Text.Encoding.GetString (बाइट [])' के लिए सर्वश्रेष्ठ अतिभारित विधि मिलान में कुछ अमान्य तर्क हैं

मैंने इस पोस्ट के आधार पर कोड को ठीक करने की कोशिश की , लेकिन फिर भी कोई सफलता नहीं मिली

string User = Encoding.UTF8.GetString("user", 0);

कोई सुझाव?


1
किस प्रकार का है searchResult.Properties["user"][0]? इसे byte[]पहली बार कास्टिंग करने की कोशिश करें
mshsayem

mshsayem गया जहाँ मैं जा रहा था। क्या आप खोज पर एक कलाकार को याद कर रहे हैं (byte[])
हैरिसन

2
आपको यह पता लगाने की आवश्यकता है कि प्रकार क्या Properties["user"][0]है। यदि आप सुनिश्चित हैं कि यह एक बाइट सरणी तो आप इस तरह डाल सकता हैprofile.User = System.Text.Encoding.UTF8.GetString((byte[])searchResult.Properties["user"][0]);
keyboardP

1
पता चलता है कि उपद्रव की कोई आवश्यकता नहीं थी। सब के बाद एन्कोडिंग के बिना उपयोगकर्ता नाम प्राप्त किया जा सकता है।
नौ

3
आप सही उत्तर का चयन क्यों नहीं करते?
अली

जवाबों:


1189

यदि आपके पास पहले से ही एक बाइट सरणी है तो आपको यह जानना होगा कि उस बाइट सरणी में इसे बनाने के लिए किस प्रकार के एन्कोडिंग का उपयोग किया गया था।

उदाहरण के लिए, यदि बाइट सरणी इस तरह बनाया गया था:

byte[] bytes = Encoding.ASCII.GetBytes(someString);

आपको इसे इस तरह वापस स्ट्रिंग में बदलने की आवश्यकता होगी:

string someString = Encoding.ASCII.GetString(bytes);

यदि आपको विरासत में मिला कोड मिल जाए, तो बाइट सरणी बनाने के लिए इस्तेमाल किया जाने वाला एन्कोडिंग तो आपको सेट होना चाहिए।


3
टिमोथी, मैंने वीबी कोड के माध्यम से देखा है और जैसा कि आपने उल्लेख किया है, मुझे बाइट सरणी नहीं मिल सकती है।
1

आपके खोज परिणाम पर, गुण संपत्ति का प्रकार क्या है?
तीमुथियुस रान्डेल

मैं केवल यह देख सकता हूं कि एक स्ट्रिंग के रूप में प्रॉपर्टीज से जुड़े कई आइटम हैं। मुझे यकीन नहीं है कि अगर तुम मुझसे पूछ रहे थे कि क्या है।
नौचाइम

16
@AndiAR एन्कोडिंग का प्रयास करें ।UTF8.GetBytes (somestring)
ओज़बेक

1
मेरी स्थिति के लिए मैंने पाया कि एनकोडिंग। यूनिकोड.गेटबाइट्स ने काम किया (लेकिन ASCII ने नहीं किया)
जेफ

106

सबसे पहले, System.Textनामस्थान जोड़ें

using System.Text;

फिर इस कोड का उपयोग करें

string input = "some text"; 
byte[] array = Encoding.ASCII.GetBytes(input);

इसे ठीक करने की उम्मीद है!


42

इसके अलावा, आप नीचे दिए गए प्रकार में एक विधि जोड़ने के लिए एक एक्सटेंशन विधि का उपयोग कर सकते हैं string:

static class Helper
{
   public static byte[] ToByteArray(this string str)
   {
      return System.Text.Encoding.ASCII.GetBytes(str);
   }
}

और इसे नीचे की तरह उपयोग करें:

string foo = "bla bla";
byte[] result = foo.ToByteArray();

12
मैं इस विधि का नाम इस तथ्य को शामिल करने के लिए रखूंगा कि यह ASCII एन्कोडिंग का उपयोग कर रहा है। कुछ इस तरह ToASCIIByteArray। मुझे नफरत है जब मुझे पता चलता है कि मैं पुस्तकालय का उपयोग कर रहा हूं तो मैं ASCII का उपयोग कर रहा हूं और मैं यह मान रहा हूं कि यह UTF-8 या कुछ और आधुनिक उपयोग कर रहा है।
टी ब्लैंक

30
var result = System.Text.Encoding.Unicode.GetBytes(text);

3
यह स्वीकृत उत्तर होना चाहिए, क्योंकि अन्य उत्तर ASCII का सुझाव देते हैं, लेकिन एन्कोडिंग या तो यूनिकोड (जिसे यह UTF16) या UTF8 है।
हाबिल

26
static byte[] GetBytes(string str)
{
     byte[] bytes = new byte[str.Length * sizeof(char)];
     System.Buffer.BlockCopy(str.ToCharArray(), 0, bytes, 0, bytes.Length);
     return bytes;
}

static string GetString(byte[] bytes)
{
     char[] chars = new char[bytes.Length / sizeof(char)];
     System.Buffer.BlockCopy(bytes, 0, chars, 0, bytes.Length);
     return new string(chars);
}

यह उन पात्रों के लिए असफल हो जाएगा जो सरोगेट जोड़ी रेंज में आते हैं .. GetBytes में एक बाइट सरणी होगी जो अंत में प्रति सरोगेट जोड़ी में एक सामान्य चार को याद करती है। GetString के अंत में खाली वर्ण होंगे। यदि Microsoft का डिफ़ॉल्ट UTF32 था, या यदि सरोगेट पेयर रेंज में वर्णों की अनुमति नहीं थी, तो यह एकमात्र तरीका होगा। या कुछ ऐसा है जो मैं नहीं देख रहा हूं? उचित तरीका स्ट्रिंग को बाइट्स में 'एनकोड' करना है।
जेरार्ड ओनील

सही है, एक व्यापक श्रेणी के लिए आप # टिमोथी रान्डेल के समाधान के समान कुछ का उपयोग कर सकते हैं: सिस्टम का उपयोग करना; System.Text का उपयोग कर; नामस्थान उदाहरण {सार्वजनिक वर्ग कार्यक्रम {सार्वजनिक स्थैतिक शून्य मुख्य (स्ट्रिंग [] args) {स्ट्रिंग s1 = "हैलो वर्ल्ड"; string s2 = "שלום עול;"; स्ट्रिंग s3 = "你好 , 世界;"; Console.WriteLine (Encoding.UTF8.GetString (Encoding.UTF8.GetBytes (S1))); Console.WriteLine (Encoding.UTF8.GetString (Encoding.UTF8.GetBytes (s2))); Console.WriteLine (Encoding.UTF8.GetString (Encoding.UTF8.GetBytes (S3))); }}}
Eran Yogev

17

एन्कोडिंग। डीफ़ॉल्ट का उपयोग क्यों नहीं किया जाना चाहिए ...

@ रान्डेल का उत्तर उपयोग करता है Encoding.Default, हालाँकि Microsoft इसके खिलाफ चेतावनी देता है :

अलग-अलग कंप्यूटर डिफॉल्ट के रूप में अलग-अलग एनकोडिंग का उपयोग कर सकते हैं, और एक कंप्यूटर पर डिफ़ॉल्ट एन्कोडिंग बदल सकते हैं। यदि आप कंप्यूटर के बीच स्ट्रीम किए गए डेटा को एनकोड और डिकोड करने के लिए डिफ़ॉल्ट एन्कोडिंग का उपयोग करते हैं या एक ही कंप्यूटर पर अलग-अलग समय पर पुनर्प्राप्त किया जाता है, तो यह उस डेटा का गलत तरीके से अनुवाद कर सकता है। इसके अलावा, डिफ़ॉल्ट संपत्ति द्वारा लौटाए गए एन्कोडिंग कोड पृष्ठ द्वारा समर्थित वर्णों के लिए असमर्थित वर्णों को मैप करने के लिए सर्वश्रेष्ठ-फिटबैक का उपयोग करता है। इन कारणों से, डिफ़ॉल्ट एन्कोडिंग का उपयोग करने की अनुशंसा नहीं की जाती है। यह सुनिश्चित करने के लिए कि एन्कोडेड बाइट्स को ठीक से डिकोड किया गया है, आपको यूनिकोड एन्कोडिंग का उपयोग करना चाहिए, जैसे UTF8Encoding या UnicodeEncoding। आप यह सुनिश्चित करने के लिए उच्च-स्तरीय प्रोटोकॉल का भी उपयोग कर सकते हैं कि एन्कोडिंग और डिकोडिंग के लिए एक ही प्रारूप का उपयोग किया जाता है।

डिफ़ॉल्ट एन्कोडिंग क्या है, इसकी जांच करने के लिए Encoding.Default.WindowsCodePage(मेरे मामले में 1250 - और दुख की बात है कि CP1250 एन्कोडिंग का कोई पूर्वनिर्धारित वर्ग नहीं है, लेकिन वस्तु को पुनः प्राप्त किया जा सकता है Encoding.GetEncoding(1250))।

Encoding.ASCII 7 बिट है, इसलिए यह मेरे मामले में भी काम नहीं करता है:

byte[] pass = Encoding.ASCII.GetBytes("šarže");
Console.WriteLine(Encoding.ASCII.GetString(pass)); // ?ar?e

... और इसके बजाय UTF-8 एन्कोडिंग का उपयोग क्यों किया जाना चाहिए ...

डिफ़ॉल्ट एन्कोडिंग भ्रामक है: .NET वास्तविक रूप से हर जगह UTF-8 का उपयोग करता है (8bit एन्कोडिंग 20. सदी के अंत तक अप्रचलित हो गया, जाँच करें अर्थात Console.OutputEncoding.EncodingName*) इसलिए कोड में परिभाषित हर निरंतर आप UTF-8 डिफ़ॉल्ट रूप से एन्कोडेड हैं - इसलिए यह तब तक उपयोग किया जाना चाहिए जब तक कि डेटा स्रोत विभिन्न एन्कोडिंग में न हो।

* यह मेरे मामले में UTF-8 है जो एक सीधा झूठ है: chcpविंडोज़ कंसोल से (cmd) 852 लौटता है - और इसे बदला नहीं जाना चाहिए, क्योंकि स्थानीयकृत सिस्टम कमांड (जैसे पिंग) में यह कोडपेज हार्डकोड है

Microsoft की अनुशंसा के बाद:

var utf8 = new UTF8Encoding();
byte[] pass = utf8.GetBytes("šarže");
Console.WriteLine(utf8.GetString(pass)); // šarže

Encoding.UTF8 दूसरों द्वारा अनुशंसित एक उदाहरण uf UTF-8 एन्कोडिंग है और इसका उपयोग सीधे या के रूप में भी किया जा सकता है

var utf8 = Encoding.UTF8 as UTF8Encoding;

... लेकिन इसका उपयोग हमेशा नहीं किया जाता है

बाइट सरणियों के लिए एन्कोडिंग को पश्चिमी देशों के यूनिकोड में "बस काम" करना चाहिए, लेकिन जैसे ही आप अपने कार्यक्रम को कुछ कम-समर्थित क्षेत्रों (जैसे पूर्वी यूरोप में) में स्थानांतरित करते हैं, यह एक वास्तविक गड़बड़ है: चेक गणराज्य में विंडोज डिफॉल्ट का उपयोग करता है (2020 में!) MS गैर-मानक 852 (उर्फ लैटिन -2) कंसोल के लिए, 1250 Windows OEM के रूप में, UTF-8 (65001) .NET (और अन्य) नए डिफ़ॉल्ट के रूप में और हमें ध्यान रखना चाहिए कि कुछ पश्चिमी यूरोपीय संघ 8bit डेटा अभी भी 1252 में है, जबकि पूर्वी यूरोप के लिए पुराने 8bit पश्चिमी मानक ISO-8859-2 (उर्फ लैटिन -2, लेकिन 852 के रूप में समान लैटिन -2 नहीं था)। ASCII का उपयोग करने का अर्थ है टोफू और 'से भरा पाठ?' यहाँ। इसलिए 21 वीं सदी के उत्तरार्ध तक, कृपया UTF-8 को स्पष्ट रूप से सेट करें ।


12

अली के उत्तर का निर्माण , मैं एक विस्तार विधि की सिफारिश करूंगा जो आपको वैकल्पिक रूप से एन्कोडिंग में पास करने की अनुमति देता है जिसका आप उपयोग करना चाहते हैं:

using System.Text;
public static class StringExtensions
{
    /// <summary>
    /// Creates a byte array from the string, using the 
    /// System.Text.Encoding.Default encoding unless another is specified.
    /// </summary>
    public static byte[] ToByteArray(this string str, Encoding encoding = Encoding.Default)
    {
        return encoding.GetBytes(str);
    }
}

और इसे नीचे की तरह उपयोग करें:

string foo = "bla bla";

// default encoding
byte[] default = foo.ToByteArray();

// custom encoding
byte[] unicode = foo.ToByteArray(Encoding.Unicode);

2
ध्यान दें कि Encoding encoding = Encoding.Defaultएक संकलन समय त्रुटि में परिणाम का उपयोग करना :CS1736 Default parameter value for 'encoding' must be a compile-time constant
डगलस गास्केल

11

निम्नलिखित दृष्टिकोण केवल तभी काम करेगा जब चार्ट 1 बाइट हो। (डिफ़ॉल्ट यूनिकोड 2 बाइट्स के बाद से काम नहीं करेगा)

public static byte[] ToByteArray(string value)
{            
    char[] charArr = value.ToCharArray();
    byte[] bytes = new byte[charArr.Length];
    for (int i = 0; i < charArr.Length; i++)
    {
        byte current = Convert.ToByte(charArr[i]);
        bytes[i] = current;
    }

    return bytes;
}

इसे सरल रखना


charऔर stringपरिभाषा के अनुसार UTF-16 हैं।
टॉम ब्लोडेट

हां डिफ़ॉल्ट है UTF-16। मैं इनपुट स्ट्रिंग के एन्कोडिंग पर कोई धारणा नहीं बना रहा हूं।
मंदार सुदामे

कोई पाठ नहीं है, लेकिन एन्कोडेड पाठ है। आपका इनपुट प्रकार है stringऔर इसलिए UTF-16 है। UTF-16 डिफ़ॉल्ट नहीं है; इसके बारे में कोई विकल्प नहीं है। आप तब char[]UTF-16 कोड इकाइयों में विभाजित हो जाते हैं । आप तब Convert.ToByte (चार) को कॉल करते हैं , जो सिर्फ U + 0000 को U + 00FF में बदलकर ISO-8859-1 करने के लिए होता है , और किसी अन्य
टॉम ब्लोडेट

समझ में आता है। स्पष्टीकरण के लिए धन्यवाद। मेरे उत्तर को अपडेट करना।
मंदार सुदामे

1
मुझे लगता है कि आप अभी भी कई आवश्यक बिंदुओं को याद कर रहे हैं। char16 बिट्स होने पर ध्यान केंद्रित करें और Convert.ToByte()उनमें से आधे को फेंक दें।
टॉम ब्लोडेट


6

जस्टिनस्टोल के संपादन (एरण योगेव का ब्लॉककॉपी का उपयोग) के लिए एक शोधन।

एनकोडिंग का उपयोग करने की तुलना में प्रस्तावित समाधान वास्तव में तेज है। समस्या यह है कि यह असमान लंबाई के बाइट सरणियों को कूटने के लिए काम नहीं करता है। जैसा कि दिया गया है, यह एक आउट-ऑफ-बाउंड अपवाद उठाता है। स्ट्रिंग से डिकोडिंग करते समय लंबाई में 1 की वृद्धि करते हुए एक अनुगामी बाइट छोड़ देता है।

मेरे लिए, की जरूरत के लिए आया था जब मैं से एनकोड करना चाहता था DataTableकरने के लिए JSON। मैं बाइनरी फ़ील्ड्स को स्ट्रिंग्स में एन्कोड करने और स्ट्रिंग बैक से डिकोड करने के लिए एक रास्ता ढूंढ रहा था byte[]

इसलिए मैंने दो वर्ग बनाए - एक जो उपरोक्त समाधान को लपेटता है (जब तारों से एन्कोडिंग यह ठीक है, क्योंकि लंबाई हमेशा समान होती है), और दूसरा जो byte[]एन्कोडिंग को संभालता है ।

मैंने एकल चरित्र को जोड़कर असमान लंबाई की समस्या को हल किया जो मुझे बताता है कि क्या द्विआधारी सरणी की मूल लंबाई विषम थी ('1') या सम ('0')

निम्नलिखित नुसार:

public static class StringEncoder
{
    static byte[] EncodeToBytes(string str)
    {
        byte[] bytes = new byte[str.Length * sizeof(char)];
        System.Buffer.BlockCopy(str.ToCharArray(), 0, bytes, 0, bytes.Length);
        return bytes;
    }
    static string DecodeToString(byte[] bytes)
    {
        char[] chars = new char[bytes.Length / sizeof(char)];
        System.Buffer.BlockCopy(bytes, 0, chars, 0, bytes.Length);
        return new string(chars);
    }
}

public static class BytesEncoder
{
    public static string EncodeToString(byte[] bytes)
    {
        bool even = (bytes.Length % 2 == 0);
        char[] chars = new char[1 + bytes.Length / sizeof(char) + (even ? 0 : 1)];
        chars[0] = (even ? '0' : '1');
        System.Buffer.BlockCopy(bytes, 0, chars, 2, bytes.Length);

        return new string(chars);
    }
    public static byte[] DecodeToBytes(string str)
    {
        bool even = str[0] == '0';
        byte[] bytes = new byte[(str.Length - 1) * sizeof(char) + (even ? 0 : -1)];
        char[] chars = str.ToCharArray();
        System.Buffer.BlockCopy(chars, 2, bytes, 0, bytes.Length);

        return bytes;
    }
}

4

इस प्रश्न का उत्तर कई बार दिया गया है, लेकिन C # 7.2 और स्पैन प्रकार की शुरुआत के साथ, असुरक्षित कोड में ऐसा करने का एक तेज़ तरीका है:

public static class StringSupport
{
    private static readonly int _charSize = sizeof(char);

    public static unsafe byte[] GetBytes(string str)
    {
        if (str == null) throw new ArgumentNullException(nameof(str));
        if (str.Length == 0) return new byte[0];

        fixed (char* p = str)
        {
            return new Span<byte>(p, str.Length * _charSize).ToArray();
        }
    }

    public static unsafe string GetString(byte[] bytes)
    {
        if (bytes == null) throw new ArgumentNullException(nameof(bytes));
        if (bytes.Length % _charSize != 0) throw new ArgumentException($"Invalid {nameof(bytes)} length");
        if (bytes.Length == 0) return string.Empty;

        fixed (byte* p = bytes)
        {
            return new string(new Span<char>(p, bytes.Length / _charSize));
        }
    }
}

ध्यान रखें कि बाइट्स यूटीएफ -16 एनकोडेड स्ट्रिंग (सी # भूमि में "यूनिकोड" कहा जाता है) का प्रतिनिधित्व करते हैं।

कुछ त्वरित बेंचमार्किंग से पता चलता है कि उपरोक्त विधियां उनके एनकोडिंग से लगभग 5 गुना तेज हैं। Unicode.GetBytes (...) / GetString (...) मध्यम आकार के तार (30-50 चार्ट) के लिए कार्यान्वयन, और बड़े तारों के साथ तेजी से। मार्शल के साथ पॉइंटर्स का उपयोग करने की तुलना में ये विधियाँ और भी तेज़ लगती हैं। कोपी (..) या बफ़र।मेरेरीकोपी (...)।


4

यदि, 'searchResult.Properties ["उपयोगकर्ता"] [0]' का परिणाम है, तो एक स्ट्रिंग है:

if ( ( searchResult.Properties [ "user" ].Count > 0 ) ) {

   profile.User = System.Text.Encoding.UTF8.GetString ( searchResult.Properties [ "user" ] [ 0 ].ToCharArray ().Select ( character => ( byte ) character ).ToArray () );

}

मुख्य बिंदु जो स्ट्रिंग को बाइट में परिवर्तित करता है [] LINQ का उपयोग करके किया जा सकता है:

.ToCharArray ().Select ( character => ( byte ) character ).ToArray () )

और उलटा:

.Select ( character => ( char ) character ).ToArray () )

3

किसी को भी ऐसा करने का कोई कारण नहीं दिखता है?

mystring.Select(Convert.ToByte).ToArray()

10
Convert.ToByte(char)आप जैसा सोचते हैं, वैसा काम नहीं होता। चरित्र '2'बाइट में परिवर्तित होता है 2, न कि बाइट में जो चरित्र का प्रतिनिधित्व करता है '2'mystring.Select(x => (byte)x).ToArray()इसके बजाय उपयोग करें ।
जैक

3

यह मेरे लिए क्या काम करता है

byte[] bytes = Convert.FromBase64String(textString);

यह तभी काम करता है जब आपके स्ट्रिंग में केवल az, AZ, 0-9, +, / होता है। किसी अन्य वर्ण को अनुमति नहीं है। deikwipedia.org/wiki/Base64
Blechdose

2

आप बहुत तेज़ और कुशल रूपांतरण करने के लिए MemoryMarshal API का उपयोग कर सकते हैं । या तो इनपुट पैरामीटर के रूप में स्वीकार Stringकिया जाएगा ।ReadOnlySpan<byte>MemoryMarshal.CastSpan<byte>ReadOnlySpan<byte>

public static class StringExtensions
{
    public static byte[] ToByteArray(this string s) => s.ToByteSpan().ToArray(); //  heap allocation, use only when you cannot operate on spans
    public static ReadOnlySpan<byte> ToByteSpan(this string s) => MemoryMarshal.Cast<char, byte>(s);
}

निम्नलिखित बेंचमार्क अंतर दिखाता है:

Input: "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s,"

|                       Method |       Mean |     Error |    StdDev |  Gen 0 | Gen 1 | Gen 2 | Allocated |
|----------------------------- |-----------:|----------:|----------:|-------:|------:|------:|----------:|
| UsingEncodingUnicodeGetBytes | 160.042 ns | 3.2864 ns | 6.4099 ns | 0.0780 |     - |     - |     328 B |
| UsingMemoryMarshalAndToArray |  31.977 ns | 0.7177 ns | 1.5753 ns | 0.0781 |     - |     - |     328 B |
|           UsingMemoryMarshal |   1.027 ns | 0.0565 ns | 0.1630 ns |      - |     - |     - |         - |

0

मेरे लिए यह काम, उसके बाद मैं अपने डेटाबेस में एक बाइट फ़ील्ड में अपनी तस्वीर डाल सकता है।

using (MemoryStream s = new MemoryStream(DirEntry.Properties["thumbnailphoto"].Value as byte[]))
{
    return s.ToArray();
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.