2010-09-24 14 views
13

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

संपादित
मैं एक और तरीका यह करने के लिए के बारे में सोचा है कि नीचे और मेरी राय में स्पष्ट है तरीकों के लिए अलग है। यह दूसरे छोर पर शून्य के साथ पैड, फिर परिणाम बदल देता है। यदि आवश्यक हो तो नहीं, क्योंकि प्रारंभ में एमएसबी जो भी हो, उसके साथ भरने को स्थानांतरित करना।

struct.unpack('<i','\0'+ bytes)[0] >> 8 
+1

+1 आपके संपादन पर +1। –

उत्तर

9

पायथन के struct मॉड्यूल आप डेटा संरचना के विभिन्न प्रकार endianness पर नियंत्रण के साथ, के रूप में बाइट्स से वर्णन कर सकते।

आप फ़ाइल से एक भी तीन-बाइट संख्या पढ़, तो आप इसे इस प्रकार परिवर्तित कर सकते हैं:

struct.unpack('<I', bytes + '\0') 

मॉड्यूल 24 बिट शब्दों का समर्थन करने के, इसलिए '\0' -padding प्रकट नहीं होता है।

संपादित करें: हस्ताक्षर संख्या अधिक कठिन हैं। आप शून्य करने के लिए उच्च-बिट कॉपी कर सकते हैं, और सेट उच्च बिट क्योंकि यह 4 बाइट (पिछले \xff यह है) .:

struct.unpack('<i', bytes + ('\0' if bytes[2] < '\x80' else '\xff')) 

के उच्चतम जगह पर ले जाता है या, python3 के लिए (bytes एक सुरक्षित है शब्द, एक बाइट सरणी के एक बाइट जाँच देता है एक int):

struct.unpack('<i', chunk + ('\0' if chunk[2] < 128 else '\xff')) 
+0

धन्यवाद, लेकिन मैं यह कहना भूल गया कि वे हस्ताक्षर किए गए हैं इसलिए सबसे महत्वपूर्ण बिट्स काम नहीं करेंगे, जैसा कि दो के पूरक की सीमित समझ के रूप में उचित है। – simonb

+0

@jolly: मैंने तदनुसार मेरा जवाब संशोधित किया है। –

+0

बेहतर स्पष्टता और गति के लिए, कोशिश करें .... .... बाइट्स [2] <'\ x80' अन्य .... ' –

7

अपने 24 बिट पूर्णांक पर हस्ताक्षर किए या अहस्ताक्षरित हैं? Bigendian या littleendian?

struct.unpack('<I', bytes + '\x00')[0] # unsigned littleendian 
struct.unpack('>I', '\x00' + bytes)[0] # unsigned bigendian 

हस्ताक्षर एक छोटे से अधिक जटिल है ... जैसा कि ऊपर अहस्ताक्षरित मूल्य मिलता है, तो ऐसा करते हैं:

signed = unsigned if not (unsigned & 0x800000) else unsigned - 0x1000000 
+0

क्षमा करें दोस्त, आपको गुना के नीचे वहां नहीं देखा। जाहिर है, मेरे पास अपवॉट करने के लिए पर्याप्त प्रतिष्ठा नहीं है लेकिन प्रयास के लिए धन्यवाद! – simonb

4

आप एक बाहरी लाइब्रेरी का उपयोग कर कोई आपत्ति नहीं है तो मेरे bitstring मॉड्यूल हो सकता है यहां सहायक

from bitstring import ConstBitStream 
s = ConstBitStream(filename='some_file') 
a = s.read('uintle:24') 

यह पहले 24 बिट्स में पढ़ता है और इसे एक हस्ताक्षरित छोटे-एंडियन पूर्णांक के रूप में व्याख्या करता है। पढ़ने के बाद s.pos 24 (स्ट्रीम में बिट स्थिति) पर सेट है, तो आप और अधिक पढ़ सकते हैं। उदाहरण के लिए यदि आप आप

l = s.readlist('10*intle:24') 

या इस्तेमाल कर सकते हैं अगले 10 पर हस्ताक्षर किए पूर्णांकों की एक सूची प्राप्त करना चाहता था आप पढ़ता के साथ आप सिर्फ स्लाइस और गुण का उपयोग करें और नहीं परेशान कर सकता है पसंद करते हैं:

a = s[0:24].uintle 

एक और विकल्प आप पहले से ही डेटा के 3 बाइट्स अगर तुम सिर्फ बनाने के लिए किया जाता है और व्याख्या फ़ाइल से:

a = ConstBitStream(bytes=b'abc').uintle 
+0

मैं इस विशेष परियोजना के लिए बाहरी पुस्तकालय का उपयोग नहीं करना चाहता, लेकिन फिर भी मैं इसे जांचूंगा। ऐसा कुछ करने के लिए प्रदर्शन कैसा है? वे संभावित रूप से लगभग 3 एमबी/एस में आ रहे होंगे, इसलिए उनमें से 130,000 प्रत्येक सेकेंड में होंगे। स्पष्ट रूप से नमूना दर आवश्यक से कहीं अधिक है इसलिए मैं उनमें से अधिकांश को त्याग सकता हूं, लेकिन यदि मैं इस पुस्तकालय का प्रबंधन नहीं करूंगा? – simonb

+0

@jolly: यदि प्रदर्शन एक चिंता है तो आपको 'संरचना' विधि से चिपकना चाहिए। बिटस्ट्रिंग (अभी के लिए) शुद्ध पायथन है इसलिए यह इसे हरा नहीं देगा। यह उचित रूप से कुशल है लेकिन जितना संभव हो सके उतना आसान, जितना संभव हो सके उतना आसान काम करने पर जोर दिया गया है - कम से कम अभी तक नहीं :) –

2

एक थोड़ी देर हो चुकी है, लेकिन यहां कुछ है कि इस स्थिति में उपयोगी हो सकता है है। यह ओपी के अद्यतन उत्तर पर बनाता है, लेकिन इसे एक ऐसे फ़ंक्शन में एकीकृत करता है जो 24 बिट इनट्स की पैक की गई फ़ाइल से मूल्यों की पूरी सूची पढ़ता है। यह ज्यादातर संरचना के साथ करता है, इसलिए मुझे लगता है कि यह उचित रूप से तेज़ होना चाहिए।

def int24_to_int(self, input_data): 
    bytelen = len(input_data) 
    frames = bytelen/3 
    triads = struct.Struct('3s' * frames) 
    int4byte = struct.Struct('<i') 
    result = [int4byte.unpack('\0' + i)[0] >> 8 for i in triads.unpack(input_data)] 
    return result