C # बाइट को int []


172

मुझे इसका उपयोग करने के intलिए ए को byte[]एक तरीके से रूपांतरित करने की आवश्यकता है BitConverter.GetBytes()। लेकिन अनिश्चित है कि अगर निम्नलिखित विनिर्देश से मेल खाता है:

एक XDR हस्ताक्षरित पूर्णांक एक 32-बिट डेटा है जो सीमा में एक पूर्णांक को कूटबद्ध करता है [-2147483648,2147483647]। पूर्णांक को दो पूरक संकेतन में दर्शाया गया है। सबसे कम और महत्वपूर्ण बाइट क्रमशः 0 और 3 हैं। पूर्णांक निम्नानुसार घोषित किए गए हैं:

स्रोत: RFC1014 3.2

मैं एक बाइट को बदलने का इरादा कैसे कर सकता हूं जो उपरोक्त विनिर्देश को पूरा करेगा?


यह अच्छा सवाल है।
चोसपांडियन

जवाबों:


217

RFC केवल यह कहने की कोशिश कर रहा है कि एक हस्ताक्षरित पूर्णांक एक सामान्य 4-बाइट पूर्णांक है जो बाइट्स के साथ बड़े-बड़े तरीके से आदेशित होता है।

अब, आप शायद थोड़ा-सा एंडियन मशीन पर काम कर रहे हैं और BitConverter.GetBytes()आपको byte[]उलट देगा। तो आप कोशिश कर सकते हैं:

int intValue;
byte[] intBytes = BitConverter.GetBytes(intValue);
Array.Reverse(intBytes);
byte[] result = intBytes;

कोड सबसे पोर्टेबल होने के लिए, हालाँकि, आप इसे इस तरह से कर सकते हैं:

int intValue;
byte[] intBytes = BitConverter.GetBytes(intValue);
if (BitConverter.IsLittleEndian)
    Array.Reverse(intBytes);
byte[] result = intBytes;

7
या ToArray का उपयोग करें। बाइट [] परिणाम = BitConverter.GetBytes (intValue) .Reverse (); ToArray ();
लार्स ट्रूजेंस

अंतिम पंक्ति क्यों byte[] result = intBytes;? intBytesपहले से ही आप चाहते हैं सरणी नहीं है ?
derHugo

2
@derHugo यह सही है, resultइस कोड टुकड़े में बेमानी है। हालांकि, मुझे लगा कि पाठक को स्पष्ट रूप से यह दिखाने के लिए यह अधिक शैक्षणिक था कि परिणाम यह मानने की तुलना में क्या था कि वे यह पता लगा सकते हैं कि परिणाम नाम के कुछ चर में निहित है intBytes। इसके अलावा, असाइनमेंट करना सस्ता है क्योंकि यह मेमोरी को कॉपी नहीं करता है और न ही नई मेमोरी को आवंटित करता है, यह सिर्फ पहले से आवंटित सरणी में एक नया नाम जोड़ता है। तो क्यों नहीं करते?
पैरासाइकल

41

इसे करने का एक और तरीका है: जैसा कि हम सभी जानते हैं 1x बाइट = 8x बिट्स और इसके अलावा, एक "रेगुलर" पूर्णांक (int32) में 32 बिट्स (4 बाइट्स) होते हैं। हम बिट्स को सही करने के लिए >> ऑपरेटर का उपयोग कर सकते हैं (>> ऑपरेटर मूल्य नहीं बदलता है।)

int intValue = 566;

byte[] bytes = new byte[4];

bytes[0] = (byte)(intValue >> 24);
bytes[1] = (byte)(intValue >> 16);
bytes[2] = (byte)(intValue >> 8);
bytes[3] = (byte)intValue;

Console.WriteLine("{0} breaks down to : {1} {2} {3} {4}",
    intValue, bytes[0], bytes[1], bytes[2], bytes[3]);

1
सरणी इनिशलाइज़र और xor (^) और & 0xFFबिट्स अनावश्यक हैं।
dtb

6
यह बड़ा-एंडियन है, इसलिए एमएसबी को पहले संग्रहीत किया जाता है, इसलिए आपको अपने सूचकांकों को उलट देना चाहिए।
Marcin Deptuła

7
क्या हम इसके विपरीत जाने का एक उदाहरण जोड़ सकते हैं? (पूर्णांक को वापस बाइट्स)
jocull

1
मैं प्रदर्शन के कारण इसका उपयोग करता हूं। यदि मुझे इस छोटे अंतर की परवाह नहीं है , तो मैं स्वीकृत उत्तर के लिए जाऊंगा।
टाइमलेस

2
आपको उस कोड को एक uncheckedब्लॉक में लपेटना चाहिए । वर्तमान में यह केवल तभी काम करता है जब कंपाइलर ओवरफ़्लो जाँच कंपाइलर सेटिंग्स में अक्षम हो।
कोडइन्चोस

25

BitConverter.GetBytes(int) लगभग वही करता है जो आप चाहते हैं, सिवाय इसके कि अंतःकरण गलत है।

जॉन स्कीट के एंडियनबिट्नेट वर्ग का उपयोग करने या उपयोग करने से पहले पूर्णांक मूल्य के भीतर बाइट्स को स्वैप करने के लिए आप IPAddress.HostToNetwork विधि का उपयोग कर सकते हैं । दोनों विधियाँ पोर्टेबिलिटी के संबंध में सही काम (tm) करती हैं।BitConverter.GetBytes

int value;
byte[] bytes = BitConverter.GetBytes(IPAddress.HostToNetworkOrder(value));

3

जब मैं इस विवरण को देखता हूं, तो मुझे लगता है, कि यह xdr पूर्णांक सिर्फ एक बड़े-स्तर का "मानक" पूर्णांक है, लेकिन इसे सबसे अधिक अस्पष्ट तरीके से व्यक्त किया गया है। दो के पूरक अंकन को U2 के रूप में बेहतर जाना जाता है, और यह वही है जो हम आज के प्रोसेसर पर उपयोग कर रहे हैं। बाइट ऑर्डर इंगित करता है कि यह एक बड़े-एंडियन अंकन है।
इसलिए, अपने प्रश्न का उत्तर देते हुए, आपको अपने ऐरे (0 <-> 3, 1 <-> 2) में तत्वों को उलटा करना चाहिए, क्योंकि वे छोटे-एंडियन में एन्कोडेड होते हैं। बस यह सुनिश्चित करने के लिए, आपको पहले BitConverter.IsLittleEndianयह देखना चाहिए कि आप किस मशीन पर चल रहे हैं।


3

ऊपर के नमूनों में यह सब कोड क्यों ...

स्पष्ट लेआउट वाली एक संरचना दोनों तरह से कार्य करती है और इसमें कोई प्रदर्शन नहीं होता है।

अद्यतन: चूँकि वहाँ एक सवाल है कि मैं कैसे अमूर्तता का वर्णन करता हूं कि अंतरात्मा के साथ कैसे व्यवहार करें। एक और कार्यान्वयन संरचना विपरीत मामले से निपट सकती है

public interface IIntToByte
{
    Int32 Int { get; set;}

    byte B0 { get; }
    byte B1 { get; }
    byte B2 { get; }
    byte B3 { get; }
}

[StructLayout(LayoutKind.Explicit)]
public struct IntToByteLE : UserQuery.IIntToByte
{
    [FieldOffset(0)]
    public Int32 IntVal;

    [FieldOffset(0)]
    public byte b0;
    [FieldOffset(1)]
    public byte b1;
    [FieldOffset(2)]
    public byte b2;
    [FieldOffset(3)]
    public byte b3;

    public Int32 Int {
        get{ return IntVal; }
        set{ IntVal = value;}
    }

    public byte B0 => b0;
    public byte B1 => b1;
    public byte B2 => b2;
    public byte B3 => b3; 
}

2
आप इसका उपयोग कैसे करेंगे? और दूसरी बात यह है कि आप इसे 'बिग-एंडियन' और 'लिटिल-एंडियन' पर भी चलाते हैं।
पीटर

@Peter यहाँ एक अद्यतन है। यह अभी भी पाली की तुलना में बेहतर प्रदर्शन करना चाहिए
स्टेन पेट्रोव

हाँ। मूल रूप से एक c ++ संघटन c # संरचना के रूप में कार्यान्वित किया जाता है। यह सुपर-फास्ट है और सभी प्रकार की चीजों को पैकिंग और अनपैकिंग के लिए अच्छा है जो बिटकॉइनर / एंडोस्कोप समस्या समाधान में अच्छी तरह से फिट नहीं होते हैं। IIRC, NAudio बहुत अच्छे प्रभाव के लिए इस दृष्टिकोण का उपयोग करता है।
क्रेग

यह सबसे अच्छा जवाब है और यह दुखद है कि यह शीर्ष नहीं है, लेकिन सिर्फ 2019 में प्रोग्रामिंग की स्थिति के बारे में आपको कुछ बताता है
जॉन इवांस


1

अन्य तरीके से उपयोग करने के लिए है BinaryPrimitives इसलिए की तरह

byte[] intBytes = BitConverter.GetBytes(123); int actual = BinaryPrimitives.ReadInt32LittleEndian(intBytes);


0
using static System.Console;

namespace IntToBits
{
    class Program
    {
        static void Main()
        {
            while (true)
            {
                string s = Console.ReadLine();
                Clear();
                uint i;
                bool b = UInt32.TryParse(s, out i);
                if (b) IntPrinter(i);
            }
        }

        static void IntPrinter(uint i)
        {
            int[] iarr = new int [32];
            Write("[");
            for (int j = 0; j < 32; j++)
            {
                uint tmp = i & (uint)Math.Pow(2, j);

                iarr[j] = (int)(tmp >> j);
            }
            for (int j = 32; j > 0; j--)
            {
                if(j%8==0 && j != 32)Write("|");
                if(j%4==0 && j%8 !=0) Write("'");
                Write(iarr[j-1]);
            }
            WriteLine("]");
        }
    }
}```

-1
byte[] Take_Byte_Arr_From_Int(Int64 Source_Num)
{
   Int64 Int64_Num = Source_Num;
   byte Byte_Num;
   byte[] Byte_Arr = new byte[8];
   for (int i = 0; i < 8; i++)
   {
      if (Source_Num > 255)
      {
         Int64_Num = Source_Num / 256;
         Byte_Num = (byte)(Source_Num - Int64_Num * 256);
      }
      else
      {
         Byte_Num = (byte)Int64_Num;
         Int64_Num = 0;
      }
      Byte_Arr[i] = Byte_Num;
      Source_Num = Int64_Num;
   }
   return (Byte_Arr);
}

कृपया अधिक विवरण जोड़ें
ग्रेगर डोरसचेंको

उत्तर के लिए धन्यवाद, आपने stackoverflow.com/a/1318948/58553 का उपयोग करने के बजाय एक नया कार्यान्वयन लिखना क्यों चुना ? (क्या आपके समाधान के साथ कोई समर्थक या विपक्ष है)
पीटर

मामले में जब परियोजना को न केवल एक भाषा के साथ विकसित करने की आवश्यकता होती है, तो यह स्थिति में भाषाओं के बीच उपयोगी एहसास कोड समानता हो सकती है जब समान विचारों को लागू किया जाना चाहिए। इस तरह से गलतियों को पकड़ने में मदद मिल सकती है। 'End #' फंक्शन 'BitConverter.GetBytes' के साथ 'Endian' की जाँच करके सुनिश्चित करें कि अधिकांश मामलों में क्या आवश्यक है। और अधिक, कुछ स्थिति में हो सकता है कि रूपांतरण का उपयोग केवल Int32 (4 बाइट्स) या Int64 (8 बाइट्स) के लिए न हो, लेकिन बाइट्स की अन्य संख्या के लिए। धन्यवाद।
वलेरी रोड

यह वास्तव में सार्वभौमिक रूप से उपयोग करने योग्य नहीं है ... यह हमेशा एक 8-बाइट सरणी देता है, जो इनपुट मानों के साथ बहुत सारे अतिरिक्त काम लाता है जो 64-बिट इनट्स नहीं हैं। मैं तार्किक रूप से एक 2-बाइट सरणी चाहता हूँ जब एक परिवर्तित Int16
Nyerguds
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.