2011-08-25 29 views
11

Tôi đang viết trình phân tích cú pháp cho định dạng nhị phân. Định dạng nhị phân này liên quan đến các bảng khác nhau, một lần nữa trong định dạng nhị phân có chứa các kích thước trường khác nhau thường (một nơi nào đó giữa 50 - 100 trong số chúng).Truy cập bitfields trong khi đọc/ghi cấu trúc dữ liệu nhị phân

Hầu hết các công trình này sẽ có bitfields và sẽ trông giống như thế này khi đại diện trong C:

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

Tôi đã xem qua các mô-đun struct nhưng nhận ra rằng độ phân giải thấp nhất là một byte và không một chút, nếu không mô-đun khá nhiều là phù hợp với công việc này.

Tôi biết bitfields được hỗ trợ bằng cách sử dụng ctypes, nhưng tôi không chắc chắn làm thế nào để giao diện cấu trúc ctypes chứa bitfields tại đây.

Tùy chọn khác của tôi là tự thao tác các bit và cho nó vào các byte và sử dụng nó với mô-đun cấu trúc - nhưng vì tôi có gần 50-100 loại cấu trúc khác nhau, viết mã để trở thành lỗi hơn- dễ bị. Tôi cũng lo lắng về hiệu quả vì công cụ này có thể được sử dụng để phân tích các gigabyte dữ liệu nhị phân lớn.

Cảm ơn.

+0

cũng có thư viện thao tác bit/bit bit của bên thứ ba. – agf

+0

Nó sẽ là một số lượng công việc, nhưng bạn có thể thiết kế một lớp có thể phân tích các định nghĩa cấu trúc kiểu C (hoặc một cái gì đó tương tự như chúng loại bỏ sự mơ hồ đóng gói) thành một bộ mặt nạ cho mỗi bitfield, đọc dữ liệu qua mô-đun cấu trúc để đạt đến cấp độ byte và cung cấp quyền truy cập '__getattr__'. –

+0

Có, tôi đã xem qua các công cụ này - [python-bitstring] (http://code.google.com/p/python-bitstring/), [Construct] (http://construct.wikispaces.com/tut-basics)), [BitReader] (https://bitbucket.org/jtoivola/bitreader/wiki/Home) - và đọc qua tài liệu của họ.Bit Reader có vẻ như một giải pháp khả thi nhưng tôi thấy [ở đây] (http://blog.mfabrik.com/2010/09/08/bitreader-python-module-for-reading-bits-from-bytes/) rằng hiệu suất sẽ là một hit lớn. Xây dựng như xa như tôi có thể tìm thấy từ tài liệu cơ bản của họ không hỗ trợ các lĩnh vực bit. Python-bitstring âm thanh đầy hứa hẹn và cần phải đào sâu hơn một chút – Tuxdude

Trả lời

4

Sử dụng bitstring (mà bạn đề cập đến bạn đang nhìn vào) nó phải đủ dễ dàng để thực hiện. Đầu tiên để tạo ra một số dữ liệu để giải mã:

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

Và sau đó giải mã nó một lần nữa chỉ là

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

mối quan tâm chính của bạn cũng có thể là tốc độ. Thư viện cũng được tối ưu hóa Python, nhưng nó không nhanh như thư viện C.

+0

Cảm ơn Scott - vâng tôi đã kiểm tra thư viện bitstring của bạn và nó rất gần với các yêu cầu của tôi. Trong thực tế, tôi đã đăng câu hỏi trong danh sách gửi thư [ở đây] (http://groups.google.com/group/python-bitstring/browse_thread/thread/2d85a909aab9d818?tvc=2). Tôi có thể hiểu nó có thể được đọc như một danh sách - nhưng tôi muốn tốt hơn là sử dụng một từ điển chỉ để thuận tiện cho khả năng đọc mã vì các cấu trúc mà tôi sẽ xử lý sẽ có nhiều hơn 20 hoặc 30 trường dễ dàng. Tôi biết nó được hỗ trợ trong gói, nhưng muốn biết làm thế nào để sử dụng nó với giải nén vì đó sẽ là chức năng chính. – Tuxdude

+0

@Ash: Bạn chưa thể giải nén vào từ điển. Tôi nghĩ rằng bạn cần một cái gì đó giống như phương pháp giải mã được đề xuất [ở đây] (http://code.google.com/p/python-bitstring/wiki/EncodeDecode), mà đã không được thực hiện một phần vì những gì tôi thực sự muốn return là một từ điển được đặt hàng - tôi không chắc chắn rằng một từ điển không có thứ tự sẽ hữu ích. Tôi sẽ suy nghĩ về nó một số chi tiết mặc dù ... –

+0

có nó có ý nghĩa để trả lại một từ điển đặt hàng nhưng tôi đoán nó hỗ trợ là hiện tại trực tiếp chỉ trong Python 3.3a0 (hoặc ít nhất là dựa trên những gì trang nói [ở đây- PEP372] (http://docs.python.org/dev/whatsnew/2.7.html) – Tuxdude

6

Tôi chưa thử nghiệm nghiêm ngặt điều này, nhưng có vẻ như nó hoạt động với các loại chưa ký (chỉnh sửa: nó cũng hoạt động với các loại ký tự/loại ngắn).

Chỉnh sửa 2: Điều này thực sự bị trúng hoặc bỏ lỡ. Nó phụ thuộc vào cách trình biên dịch của thư viện đóng gói các bit vào cấu trúc, mà không được chuẩn hóa. Ví dụ: với gcc 4.5.3, nó hoạt động miễn là tôi không sử dụng thuộc tính để đóng gói cấu trúc, tức là __attribute__ ((__packed__)) (vì vậy thay vì 6 byte, nó được đóng gói thành 4 byte, bạn có thể kiểm tra với __alignof__sizeof). Tôi có thể làm cho nó gần như làm việc bằng cách thêm _pack_ = True vào định nghĩa Structure Structurepes, nhưng nó không thành công cho fieldE. Ghi chú gcc: "Bù đắp trường bit được đóng gói 'fieldE' đã thay đổi trong GCC 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]))) 

Output:

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

C:

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

Xem ví dụ được kiểm tra mà không cần bất kỳ mã C hoặc dll nào cả ở [Python có loại bitfield không?] (Http://stackoverflow.com/a/11481471/507544) – nealmcb

+0

@nealmcb - Ví dụ của bạn đại diện cho một cách để lưu trữ dữ liệu đó trong chính Python. Nhưng làm thế nào để bạn nhập hoặc xuất dữ liệu như vậy từ/đến một dòng byte có thể được đọc/ghi vào đĩa hoặc có thể được recvd/gửi qua mạng? – Tuxdude

+0

@ash Đó là những gì mà công đoàn dành cho, và trường 'flags.asbyte' trong ví dụ đó. Cảm ơn bạn đã chỉ ra rằng nó không rõ ràng. Tôi đã đánh bóng văn bản ở đó để làm cho nó rõ ràng hơn một chút. Heh :) – nealmcb

Các vấn đề liên quan