2009-05-22 9 views
7

मैं बाइनरी रीडर क्लास के साथ एक बाइनरी फ़ाइल पढ़ने की कोशिश कर रहा हूं, और मुझे इसे UInt32 के ब्लॉक के रूप में पढ़ने की आवश्यकता है, और उसके बाद कुछ बिट स्थानांतरण आदि।BinaryReader.ReadUInt32() बिट पैटर्न को उलट क्यों करता है?

लेकिन, किसी कारण से जब मैं ReadUInt32 विधि का उपयोग करता हूं तो थोड़ा ऑर्डर उलट जाता है।

मैं उदाहरण के लिए एक फ़ाइल जहां पहले चार बाइट्स हेक्स, 0x12345678 में इस तरह दिखता है, तो वे इस तरह अंत ReadUInt32 द्वारा पढ़ा जा रहा करने के बाद: 0x78563412

[0x00000000] 0x12 byte 
[0x00000001] 0x34 byte 
[0x00000002] 0x56 byte 
[0x00000003] 0x78 byte 

ऐसा क्यों है:

अगर मैं ReadBytes का उपयोग (4) विधि, मैं उम्मीद सरणी मिल सकता है? क्या यह वही तरीका है .नेट स्मृति में यूंट्स का प्रतिनिधित्व करता है? क्या यह विभिन्न प्लेटफार्मों में समान है (मैं 64 बिट विंडोज 7 चला रहा हूं, नेट 3.5 एसपी 1)?

+0

क्या आप हमें यह बताकर हमारी जिज्ञासा को रद्द कर सकते हैं कि आपने इसे कैसे ठीक किया? :) –

+1

बेशक :) वास्तव में इससे कोई फर्क नहीं पड़ता कि बाइट ऑर्डर किस तरह से है, जब तक यह प्लेटफ्रम (x64, x86) में संगत है, मैं अभी भी बिट्स को निकालने के लिए कर सकता हूं, मुझे बस थोड़ा सा बदलना है स्थानांतरण। जहां तक ​​मैं देख सकता हूं, यूंट सामान्य रूप से छोटे-एंडियन के रूप में संग्रहीत होता है, न कि केवल ReadUInt32 द्वारा निर्मित यूंट, जिससे सबकुछ आसान हो जाता है। –

उत्तर

8

यह एक endianness मुद्दा हो रहा है। The docs कहते हैं कि ReadUint32 छोटे-अंत में पढ़ता है, इसलिए पहला बाइट कम से कम महत्वपूर्ण है, इसलिए यह सबसे कम स्मृति स्थान पर जाता है। आपका लेखक बड़ा एंडियन होना चाहिए?

BinaryWriter.Write(UInt32)says it writes थोड़ा-एंडियन भी। क्या आपका द्विआधारी डेटा स्रोत बाइनरीवाइटर नहीं है?

अनिवार्य रूप से आप इसे ठीक करने के लिए क्या करने की जरूरत यह है:

uint a = 0x12345678; 
uint b = ((a & 0x000000FF) << 24) + ((a & 0x0000FF00) << 8) + ((a & 0x00FF0000) >> 8) + ((a & 0xFF000000) >> 24); 

यह कम से कम-महत्वपूर्ण बाइट तक 24 बिट, 2 LSB अप 8 बिट, 3 LSB नीचे 8 बिट, और बदलाव 4 बिट एलएसबी (एमएसबी) 24 बिट नीचे। ऐसा करना कई पुस्तकालयों में शामिल है।

शायद BitConverter का उपयोग कर थोड़ा और स्पष्ट होगा:

uint a = 0x12345678; 
byte[] bytes = BitConverter.GetBytes(a); 
// Swap byte order 
uint b = BitConverter.ToUInt32(new byte[] { bytes[3], bytes[2], bytes[1], bytes[0] }, 0); 
8

हां, यह आपके कंप्यूटर हार्डवेयर मेमोरी में यूंट्स को कैसे स्टोर करता है इसके साथ करना है। यह विभिन्न प्लेटफार्मों में अलग हो सकता है, हालांकि अधिकांश डेस्कटॉप कंप्यूटर समान होना चाहिए।

यह endianness कहा जाता है - विकिपीडिया यहाँ देखें:

http://en.wikipedia.org/wiki/Endian

1

इस मंच Endianess का एक मुद्दा है। जब आप किसी स्ट्रीम से डेटा पढ़ते हैं तो आपको इसके अनुसार अंतहीनता के अनुसार इसे पढ़ना होगा। यदि आपने .Net में डेटा बनाया है, तो .Net इसे सही तरीके से पढ़ेगा।

+0

लॉल 3 विकिपीडिया लिंक 1 मिनट से कम में। इसके लिए एक बैज होना चाहिए! –

2

एंडियन बाइनरी रीडर और एंडियनबिट कनवर्टर जैसे एंडियन * कक्षाओं के लिए जॉन स्कीट की MiscUtil लाइब्रेरी में देखें।

http://www.yoda.arachsys.com/csharp/miscutil/

0

पढ़ें Generic BinaryReader and BinaryWriter Extensions, सामान्य को संभालने के लिए एक शानदार तरीका अप्रबंधित रास्ता कास्टिंग।

वीबी के लिए।नेट (केवल सुरक्षित कोड, यह भी सी # में प्राप्त किया जा सकता) निम्नलिखित का उपयोग करें:

आयात System.IO आयात System.Runtime.CompilerServices आयात System.Runtime.InteropServices

<HideModuleName()> 
Public Module BinaryReaderExtensions 

<Extension()> 
Public Function Read(Of T As Structure)(br As BinaryReader) As T 
    Dim bytes = br.ReadBytes(Marshal.SizeOf(GetType(T))) 
    Dim handle = GCHandle.Alloc(bytes, GCHandleType.Pinned) 
    Return Marshal.PtrToStructure(handle.AddrOfPinnedObject, GetType(T)) 
End Function 

<Extension()> 
Public Function ReadReverse(Of T As Structure)(br As BinaryReader) As T 
    Dim bytes = br.ReadBytes(Marshal.SizeOf(GetType(T))).Reverse.ToArray 
    Dim handle = GCHandle.Alloc(bytes, GCHandleType.Pinned) 
    Return Marshal.PtrToStructure(handle.AddrOfPinnedObject, GetType(T)) 
End Function 

End Module 

अब आप लागू कर सकते हैं BinaryWriter आदि के लिए BitConverter के लिए समान कार्यक्षमता

संबंधित मुद्दे