2017-06-15 83 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