2011-12-23 10 views
21

मैं जानकारी के सभी अलग-अलग बिट्स पढ़ने के लिए प्रोग्राम का उपयोग करके एसटीएफएस फ़ाइल प्रारूप की अपनी समझ में सुधार करने की कोशिश कर रहा हूं। किसी ऑफसेट के संदर्भ में एक वेबसाइट का उपयोग करना जिसमें कोई जानकारी है, मैंने कुछ कोड लिखा है जिसमें एक बाइनरी रीडर फ़ाइल के माध्यम से जाता है और मानों को सही चर में रखता है।सी # - बिग एंडियन में बाइनरी रीडर?

समस्या यह है कि सभी डेटा बिग एंडियन होने के लिए तैयार है, और बाइनरी रीडर पढ़ने वाली सब कुछ लिटिल एंडियन है। तो, इसे ठीक करने के बारे में जाने का सबसे अच्छा तरीका क्या है?

क्या मैं बाइनरी रीडर की एक नकली कक्षा बना सकता हूं जो बाइट्स की एक उलटा सरणी देता है? क्या कक्षा में उदाहरण में कुछ ऐसा बदल सकता है जो इसे बड़े एंडियन में पढ़ेगा, इसलिए मुझे सबकुछ फिर से लिखना नहीं है?

किसी भी मदद की सराहना की जाती है।

संपादित करें: मैंने पैरामीटर के रूप में एन्कोडिंग। बिगइंडियन यूनिकोड जोड़ने की कोशिश की, लेकिन यह अभी भी थोड़ा एंडियन पढ़ता है।

+4

स्कीट एक ने लिखा है::

/// <summary> /// Get's a byte array from a point in a source byte array and reverses the bytes. Note, if the current platform is not in LittleEndian the input array is assumed to be BigEndian and the bytes are not returned in reverse order /// </summary> /// <param name="byteArray">The source array to get reversed bytes for</param> /// <param name="startIndex">The index in the source array at which to begin the reverse</param> /// <param name="count">The number of bytes to reverse</param> /// <returns>A new array containing the reversed bytes, or a sub set of the array not reversed.</returns> public static byte[] ReverseForBigEndian(this byte[] byteArray, int startIndex, int count) { if (BitConverter.IsLittleEndian) return byteArray.Reverse(startIndex, count); else return byteArray.SubArray(startIndex, count); } public static byte[] Reverse(this byte[] byteArray, int startIndex, int count) { byte[] ret = new byte[count]; for (int i = startIndex + (count - 1); i >= startIndex; --i) { byte b = byteArray[i]; ret[(startIndex + (count - 1)) - i] = b; } return ret; } public static byte[] SubArray(this byte[] byteArray, int startIndex, int count) { byte[] ret = new byte[count]; for (int i = 0; i < count; ++i) ret[0] = byteArray[i + startIndex]; return ret; } 

तो इस उदाहरण कोड की कल्पना:

इस तरह के रूप में, मैं वास्तव में सिर्फ कुछ बाइट [] एक्सटेंशन का एक बड़ा वर्ग बनाने के बारे में लिखा http: // www.yoda.arachsys.com/csharp/miscutil/ –

+0

@ हंसपैसेंट, क्या यह उन डीएलएस में से एक होगा जिसके लिए मुझे अपना कोड ओपन सोर्स बनाना होगा? कुछ डीएलएस की आवश्यकता क्यों होती है? – mowwwalker

+0

वॉकरर्नो मैंने अपना जवाब हटा दिया क्योंकि zmbq ने अनिवार्य रूप से मेरे सामने 3 मिनट पहले ही जवाब दिया था। अंतहीनता की अवधारणा बाइट एरे पर लागू नहीं होती है, केवल शब्दों, पासवर्ड, qwords, आदि के लिए, जो 2, 4, 8 और बाइट्स पर समूह के लिए है। मुझे खेद है कि अगर इसका मतलब बहुत सारे कोड को बदलना है, लेकिन एक आदमी को ऐसा करना है जो एक आदमी को करना है। –

उत्तर

31

मैं नहीं आमतौर पर अपने ही सवालों के जवाब देने से एक हूँ, लेकिन मैं कुछ भी किया है कि वास्तव में क्या मैं कुछ सरल कोड के साथ करना चाहता था:

class BinaryReader2 : BinaryReader { 
    public BinaryReader2(System.IO.Stream stream) : base(stream) { } 

    public override int ReadInt32() 
    { 
     var data = base.ReadBytes(4); 
     Array.Reverse(data); 
     return BitConverter.ToInt32(data, 0); 
    } 

    public Int16 ReadInt16() 
    { 
     var data = base.ReadBytes(2); 
     Array.Reverse(data); 
     return BitConverter.ToInt16(data, 0); 
    } 

    public Int64 ReadInt64() 
    { 
     var data = base.ReadBytes(8); 
     Array.Reverse(data); 
     return BitConverter.ToInt64(data, 0); 
    } 

    public UInt32 ReadUInt32() 
    { 
     var data = base.ReadBytes(4); 
     Array.Reverse(data); 
     return BitConverter.ToUInt32(data, 0); 
    } 

} 

मैं जानता था कि क्या हो रहा है मैं चाहता था, लेकिन मुझे नहीं पता था कि इसे कैसे लिखना है। मुझे यह पृष्ठ मिला और इससे मदद मिली: http://www.codekeep.net/snippets/870c4ab3-419b-4dd2-a950-6d45beaf1295.aspx

+12

ऑफ-विषय, लेकिन आपकी कक्षा के फ़ील्ड ('a16' आदि) अनावश्यक हैं। आप निर्माण के दौरान उन्हें एक सरणी असाइन करते हैं, लेकिन प्रत्येक विधि के भीतर आप उस सरणी को 'रीड' फ़ंक्शन द्वारा लौटाए गए एक नए सरणी के साथ प्रतिस्थापित करते हैं। आप प्रत्येक विधि में 'var a32 = base.ReadBytes ...' डाल सकते हैं और फ़ील्ड से छुटकारा पा सकते हैं। –

+15

वे अनावश्यक नहीं हैं, वे हानिकारक हैं। एक साझा स्थिति की स्थिति में एक थ्रेड-सुरक्षित कोड क्या है (संभावित रूप से, शेयर अंतर्निहित धारा को अनदेखा कर रहा है) को चालू करना। – skolima

+4

आप शायद रिवर्सिंग से पहले 'बिटकॉन्टर.इस्लिटल इंडियन' की जांच करना चाहते हैं। यदि यह 'झूठा' है तो आपको रिवर्स की आवश्यकता नहीं है। –

5

मैं एसटीएफएस से परिचित नहीं हूं, लेकिन अंतहीनता बदलना अपेक्षाकृत आसान है। "नेटवर्क ऑर्डर" बड़ा एंडियन है, इसलिए आपको बस नेटवर्क से होस्ट ऑर्डर करने का अनुवाद करना है।

यह आसान है क्योंकि पहले से ही कोड है जो ऐसा करता है। IPAddress.NetworkToHostOrder को देखो, जैसा कि यहां बताया: ntohs() and ntohl() equivalent?

9

आईएमएचओ थोड़ा बेहतर उत्तर है क्योंकि इसे एक अलग वर्ग की नई आवश्यकता नहीं है, जिससे बड़े-एंडियन कॉल स्पष्ट हो जाते हैं और बड़े और छोटे-एंडियन कॉल की अनुमति मिलती है धारा में मिश्रित हो।

public static class Helpers 
{ 
    // Note this MODIFIES THE GIVEN ARRAY then returns a reference to the modified array. 
    public static byte[] Reverse(this byte[] b) 
    { 
    Array.Reverse(b); 
    return b; 
    } 

    public static UInt16 ReadUInt16BE(this BinaryReader binRdr) 
    { 
    return BitConverter.ToUInt16(binRdr.ReadBytesRequired(sizeof(UInt16)).Reverse(), 0); 
    } 

    public static Int16 ReadInt16BE(this BinaryReader binRdr) 
    { 
    return BitConverter.ToInt16(binRdr.ReadBytesRequired(sizeof(Int16)).Reverse(), 0); 
    } 

    public static UInt32 ReadUInt32BE(this BinaryReader binRdr) 
    { 
    return BitConverter.ToUInt32(binRdr.ReadBytesRequired(sizeof(UInt32)).Reverse(), 0); 
    } 

    public static Int32 ReadInt32BE(this BinaryReader binRdr) 
    { 
    return BitConverter.ToInt32(binRdr.ReadBytesRequired(sizeof(Int32)).Reverse(), 0); 
    } 

    public static byte[] ReadBytesRequired(this BinaryReader binRdr, int byteCount) 
    { 
    var result = binRdr.ReadBytes(byteCount); 

    if (result.Length != byteCount) 
     throw new EndOfStreamException(string.Format("{0} bytes required from stream, but only {1} returned.", byteCount, result.Length)); 

    return result; 
    } 
} 
+7

रिवर्सिंग से पहले 'बिटकॉन्टर.इस्लाइट इंडियन' की जांच करना याद रखें। –

4

मेरी राय में, आप इसे करने से सावधान रहना चाहते हैं। बिगएंडियन से लिटिलएंडियन में कनवर्ट करना चाहते हैं, यदि बाइट्स पढ़ रहे हैं तो बिगएंडियन में हैं और उनके खिलाफ गणना ओएस लिटिलएंडियन में काम कर रही है।

सी # अब एक खिड़की नहीं है। मोनो जैसे बंदरगाहों और विंडोज़ फोन 7/8, एक्सबॉक्स 360/एक्सबॉक्स वन, विंडवोस सीई, विंडोज 8 मोबाइल, लिनक्स विद मोनो, मोनो के साथ ऐप्पल आदि जैसे अन्य माइक्रोसॉफ्ट प्लेटफार्मों के साथ। यह काफी संभव है कि ऑपरेटिंग प्लेटफार्म हो बिग इंडियन, यदि आप किसी भी चेक किए बिना कोड को परिवर्तित करते हैं तो आप अपने आप को खराब कर देंगे।

बिटककॉन्टर पर पहले से ही "IsLittleEndian" नामक एक फ़ील्ड है जिसका उपयोग आप यह निर्धारित करने के लिए कर सकते हैं कि ऑपरेटिंग वातावरण LittleEndian में है या नहीं। फिर आप सशर्त रूप से उलटा कर सकते हैं।

byte[] fontBytes = byte[240000]; //some data loaded in here, E.G. a TTF TrueTypeCollection font file. (which is in BigEndian) 

int _ttcVersionMajor = BitConverter.ToUint16(fontBytes.ReverseForBigEndian(4, 2), 0); 

//output 
_ttcVersionMajor = 1 //TCCHeader is version 1