2011-08-25 13 views
11

मैं एक बाइनरी प्रारूप के लिए एक पार्सर लिख रहा हूं। इस बाइनरी प्रारूप में अलग-अलग टेबल शामिल होते हैं जो बाइनरी प्रारूप में होते हैं, जिसमें आमतौर पर अलग-अलग फ़ील्ड आकार होते हैं (कहीं 50 से 100 के बीच)।द्विआधारी डेटा संरचनाओं को पढ़ने/लिखते समय बिटफील्ड तक पहुंच

इन संरचनाओं में से अधिकांश bitfields होगा और जब सी में प्रतिनिधित्व इस तरह दिखेगा:

struct myHeader 
{ 
    unsigned char fieldA : 3 
    unsigned char fieldB : 2; 
    unsigned char fieldC : 3; 
    unsigned short fieldD : 14; 
    unsigned char fieldE : 4 
} 

मैं struct मॉड्यूल में आए लेकिन महसूस किया कि अपने न्यूनतम संकल्प एक बाइट और नहीं एक सा हो गया था, अन्यथा इस काम के लिए मॉड्यूल काफी सही था।

मुझे पता है कि बिटफिल्ड को सीटीपीएस का उपयोग करके समर्थित किया जाता है, लेकिन मुझे यकीन नहीं है कि यहां बिटफिल्ड वाले सीटीपीएस स्ट्रक्चर को इंटरफ़ेस कैसे करें।

मेरा दूसरा विकल्प बिट्स में हेरफेर करना है और इसे बाइट्स में खिलााना है और इसे स्ट्रक्चर मॉड्यूल के साथ उपयोग करना है - लेकिन जब से मेरे पास 50-100 विभिन्न प्रकार के संरचनाएं हैं, तो इसके लिए कोड लिखना अधिक त्रुटि हो जाता है- होने का खतरा। मैं दक्षता के बारे में भी चिंतित हूं क्योंकि इस उपकरण का उपयोग बाइनरी डेटा के बड़े गीगाबाइट को पार्स करने के लिए किया जा सकता है।

धन्यवाद।

+0

तीसरे पक्ष बिट सरणी/बिट मैनिपुलेशन पुस्तकालय भी हैं। – agf

+0

यह एक उचित मात्रा में काम होगा, लेकिन आप संभवतः एक वर्ग तैयार कर सकते हैं जो प्रत्येक बिटफील्ड के लिए मास्क के सेट में सी-स्टाइल संरचना परिभाषाओं (या पैकिंग अस्पष्टता को समाप्त करने वाले समान) को पार्स कर सकता है, के माध्यम से डेटा पढ़ें बाइट स्तर तक पहुंचने के लिए संरचना मॉड्यूल, और '__getattr__' पहुंच प्रदान करें। –

+0

हाँ अब मैं इन उपकरणों में आया - [पायथन-बिटस्ट्रिंग] (http://code.google.com/p/python-bitstring/), [निर्माण] (http://construct.wikispaces.com/tut-basics), [बिट्रियर] (https://bitbucket.org/jtoivola/bitreader/wiki/Home) - और उनके दस्तावेज़ों के माध्यम से पढ़ना।बिट रीडर एक व्यवहार्य समाधान की तरह लगता है, लेकिन मैं [यहां] को देखने के (http://blog.mfabrik.com/2010/09/08/bitreader-python-module-for-reading-bits-from-bytes/) कि प्रदर्शन एक बड़ी हिट होने वाला है। जहां तक ​​मैं अपने मूल दस्तावेज से प्राप्त कर सकता हूं, निर्माण बिट फ़ील्ड का समर्थन नहीं करता है। अजगर-bitstring होनहार लग रहा है और गहरी बिट में खुदाई करने के लिए की जरूरत है – Tuxdude

उत्तर

4

का उपयोग करना bitstring (जो आप का उल्लेख आप देख रहे हैं) यह काफी आसान लागू करने के लिए होना चाहिए। सबसे पहले डिकोड करने के लिए कुछ डेटा बनाने के लिए:

>>> myheader = "3, 2, 3, 14, 4" 
>>> a = bitstring.pack(myheader, 1, 0, 5, 1000, 2) 
>>> a.bin 
'00100101000011111010000010' 
>>> a.tobytes() 
'%\x0f\xa0\x80' 

और फिर इसे फिर से डिकोडिंग सिर्फ

>>> a.readlist(myheader) 
[1, 0, 5, 1000, 2] 

आपका मुख्य चिंता अच्छी तरह से गति हो सकती है। पुस्तकालय अच्छी तरह से पाइथन अनुकूलित है, लेकिन यह सी पुस्तकालय के रूप में लगभग तेज़ नहीं होगा।

+0

धन्यवाद स्कॉट - हाँ मैंने आपकी बिटस्ट्रिंग लाइब्रेरी की जांच की है और यह वास्तव में मेरी आवश्यकताओं के बहुत करीब आता है। असल में मैंने मेलिंग सूची [यहां] में प्रश्न पोस्ट किया (http://groups.google.com/group/python-bitstring/browse_thread/thread/2d85a909aab9d818?tvc=2)। मैं समझ सकता हूं कि इसे एक सूची के रूप में पढ़ा जा सकता है - लेकिन मैं कोड पठनीयता की सुविधा के लिए अधिमानतः एक शब्दकोश का उपयोग करना चाहता हूं क्योंकि जिन आर्किटेक्ट्स के साथ मैं काम कर रहा हूं, उनमें 20 या 30 से अधिक फ़ील्ड आसानी से होंगे। मुझे पता है कि यह पैक में समर्थित है, लेकिन यह जानना चाहेंगे कि इसे अनपैक के साथ कैसे उपयोग किया जाए क्योंकि यह प्राथमिक कार्यक्षमता होगी। – Tuxdude

+0

@Ash: आप अभी तक एक शब्दकोश में अनपैक नहीं कर सकते हैं। मुझे लगता है कि आपको प्रस्तावित डीकोड विधि की तरह कुछ चाहिए [यहां] (http://code.google.com/p/python-bitstring/wiki/EncodeDecode), जो आंशिक रूप से नहीं किया गया है क्योंकि मैं वास्तव में क्या चाहता हूं वापसी एक आदेशित शब्दकोश है - मुझे यकीन नहीं है कि एक अनियंत्रित शब्दकोश उपयोगी होगा। मैं इसके बारे में कुछ और सोचूंगा ... –

+0

हाँ यह आदेश दिया गया शब्दकोश वापस करने के लिए समझ में आता है, लेकिन मुझे लगता है कि इसका समर्थन सीधे पायथन 3.3a0 में मौजूद है (या कम से कम पेज के बारे में क्या कहता है [यहां- पीईपी 372] (http://docs.python.org/dev/whatsnew/2.7.html) – Tuxdude

6

मैंने कठोर परीक्षण नहीं किया है, लेकिन ऐसा लगता है कि यह हस्ताक्षरित प्रकारों के साथ काम करता है (संपादित करें: यह हस्ताक्षरित बाइट/लघु प्रकारों के साथ भी काम करता है)।

संपादित करें 2: यह वास्तव में हिट या मिस है। यह पुस्तकालय के कंपाइलर ने बिट्स को संरचना में पैक करने के तरीके पर निर्भर करता है, जो मानकीकृत नहीं है। उदाहरण के लिए, जीसीसी 4.5.3 के साथ यह तब तक काम करता है जब तक मैं संरचना को पैक करने के लिए विशेषता का उपयोग नहीं करता, यानी __attribute__ ((__packed__)) (इसलिए 6 बाइट्स के बजाय इसे 4 बाइट्स में पैक किया जाता है, जिसे आप __alignof__ और sizeof से जांच सकते हैं)। मैं इसे _pack_ = True को ctypes संरचना परिभाषा में जोड़कर लगभग काम कर सकता हूं, लेकिन यह fieldE के लिए विफल रहता है। जीसीसी नोट्स: "जीसीसी 4.4 में पैक किए गए बिट-फील्ड 'फ़ील्डई का ऑफसेट बदल गया है"।

import ctypes 

class MyHeader(ctypes.Structure): 
    _fields_ = [ 
     ('fieldA', ctypes.c_ubyte, 3), 
     ('fieldB', ctypes.c_ubyte, 2), 
     ('fieldC', ctypes.c_ubyte, 3), 
     ('fieldD', ctypes.c_ushort, 14), 
     ('fieldE', ctypes.c_ubyte, 4), 
    ] 

lib = ctypes.cdll.LoadLibrary('C/bitfield.dll') 

hdr = MyHeader() 
lib.set_header(ctypes.byref(hdr)) 

for x in hdr._fields_: 
    print("%s: %d" % (x[0], getattr(hdr, x[0]))) 

आउटपुट:

fieldA: 3 
fieldB: 1 
fieldC: 5 
fieldD: 12345 
fieldE: 9 

सी:

typedef struct _MyHeader { 
    unsigned char fieldA : 3; 
    unsigned char fieldB : 2; 
    unsigned char fieldC : 3; 
    unsigned short fieldD : 14; 
    unsigned char fieldE : 4; 
} MyHeader, *pMyHeader; 

int set_header(pMyHeader hdr) { 

    hdr->fieldA = 3; 
    hdr->fieldB = 1; 
    hdr->fieldC = 5; 
    hdr->fieldD = 12345; 
    hdr->fieldE = 9; 

    return(0); 
} 
+0

पर किसी भी सी कोड या DLLs सब पर की आवश्यकता के बिना एक परीक्षण किया उदाहरण देखें (http://stackoverflow.com/a/11481471/507544) – nealmcb

+0

@nealmcb [क्या अजगर एक bitfield प्रकार है?] - अपने उदाहरण के लिए एक रास्ता का प्रतिनिधित्व करता है ऐसे डेटा को पायथन के भीतर ही स्टोर करने के लिए। लेकिन आप इस तरह के डेटा को बाइट्स की धारा से आयात या निर्यात कैसे करते हैं जिसे डिस्क पर पढ़ा/लिखा जा सकता है या नेटवर्क पर recvd/भेजा जा सकता है? – Tuxdude

+0

@ash यही वह संघ है, और उस उदाहरण में 'flags.asbyte' फ़ील्ड। यह इंगित करने के लिए धन्यवाद कि यह इतना स्पष्ट नहीं था। मैंने इसे थोड़ा और स्पष्ट करने के लिए वहां टेक्स्ट को पॉलिश किया है। हे :) – nealmcb

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