2017-06-15 72 views
1

我最近繼承了一個項目,在該項目中我們反序列化了一個由我無法更改的系統寫出的一串數據(希望他們使用標準串行器,但我無法更改此項)。在大多數情況下,我能夠使用ctypes來表示結構並將數據正確地轉換爲Python,但是我們有一些情況下底層的數據結構是一團糟(再次,無論我嘗試過多少次都無法改變)。當C結構定義如下2例正在推動我堅果試圖找到一種有效的方式是:在Python中使用動態數組反序列化C結構

簡單的例子:

struct b{ 
    int data; 
    int more_data; 
}; 

struct a{ 
    int num_entries; 
    b* data; 
}; 

,當它是序列化,擠滿了b *數據進入內存,就好像它是一個靜態數組減速。

這裏來最恐怖的情況下,我不得不面對:

struct c{ 
    int a; 
    int b; 
}; 

struct b{ 
    int random_data; 
    c* data; 
    int more_data; 
}; 

struct a{ 
    int len; // This actually defines the length in struct b for "data" array size 
    b nested_data; 
    c why_not_it_is_this_poorly_organized; 
} 

任何幫助將肯定可以理解的!

+0

看起來很像https://stackoverflow.com/questions/8392203/dynamic-arrays-and-structures-in-structures-in-python?rq=1 –

+0

這問題正在朝另一個方向發展,它不會解決您接收字節流然後需要將數據轉換回此結構表示形式的情況。 – FrenchToast

+0

使用一些依賴於平臺的(至多)二進制格式是一個非常糟糕的主意。使用文本格式或至少定義獨立於C平臺的二進制格式。然後在兩邊使用適當的編組。 – Olaf

回答

0

你試過看看Python bitstring API?從這裏開始,您可以編寫一些方法通過切分數組來反序列化數據。它可能是這個樣子:

def parse_c(buffer): 
    # Parse data into list 

def parse_b(buffer): 
    # Parse first int of B 
    list = parse_c(buffer[8:-8]) # skip first/last int 
    # Parse last int of B 

def parse_a(buffer): 
    # Parse len (you could also pass this into parse_b, but b can figure it out from the size) 
    b = parse_b(buffer[-8:-16]) 
    c = parse_c(buffer[-16:]) 
+1

這似乎並沒有以任何方式實際上有所幫助。現在你有位而不是字節。如果有的話,這是一個倒退。 – user2357112

+0

正如文檔所言:「Bitstrings不知道或不在乎它們是如何創建的,它們只是一些集合,這意味着您可以自由地以任何有意義的方式解釋它們。」請參閱:https://pythonhosted.org/bitstring/interpretation.html例如:'length = buffer.int'來獲取第一個int。 – Stormswept

+0

這可能是我必須去的方式,但我希望在不分析數據字段的情況下做到這一點,因爲我們記錄的每個日誌都有大約1TB的數據,並且有大約10,000個數據數據類型被表示。我擔心切片和嵌套函數調用的效率,但是,它比我迄今爲止提出的任何東西都要好!謝謝! – FrenchToast