从c中创建的struct读取python中的struct

Sch*_*eck 13 c python

我对使用Python非常陌生,并且对C非常生疏,所以我提前道歉我的声音是多么愚蠢和/或丢失.

我在C中有函数创建一个包含数据的.dat文件.我使用Python打开文件来读取文件.我需要阅读的一件事是在C函数中创建并以二进制打印的结构.在我的Python代码中,我在文件的相应行中读取结构.我已经尝试了逐项解开stuct项目并且整体没有成功.结构中的大多数项目在C代码中被声明为"真实".我正在与其他人一起研究这个代码,主要的源代码是他的,并且已经将变量声明为"真实".我需要把它放在一个循环中,因为我想读取目录中以'.dat'结尾的所有文件.要开始循环,我有:

for files in os.listdir(path):
  if files.endswith(".dat"):
    part = open(path + files, "rb")
    for line in part:
Run Code Online (Sandbox Code Playgroud)

然后我读取包含结构的那一行之前的所有行.然后我到达那条线并且:

      part_struct = part.readline()
      r = struct.unpack('<d8', part_struct[0])
Run Code Online (Sandbox Code Playgroud)

我试图只读取存储在结构中的第一件事.我在这里看到了一个这样的例子.当我尝试这个时,我收到的错误是:

struct.error: repeat count given without format specifier
Run Code Online (Sandbox Code Playgroud)

我会接受别人可以给我的任何和所有提示.我已经坚持了几天,并尝试了许多不同的东西.老实说,我认为我不理解struct模块,但我已尽可能多地阅读它.

谢谢!

jfs*_*jfs 15

您可以使用ctypes.Structurestruct.Struct指定文件的格式.要从@ perreal的答案中读取C代码生成的文件中的结构:

"""
struct { double v; int t; char c;};
"""
from ctypes import *

class YourStruct(Structure):
    _fields_ = [('v', c_double),
                ('t', c_int),
                ('c', c_char)]

with open('c_structs.bin', 'rb') as file:
    result = []
    x = YourStruct()
    while file.readinto(x) == sizeof(x):
        result.append((x.v, x.t, x.c))

print(result)
# -> [(12.100000381469727, 17, 's'), (12.100000381469727, 17, 's'), ...]
Run Code Online (Sandbox Code Playgroud)

io.BufferedIOBase.readinto().它在Python 3中受支持,但在Python 2.7中没有记录默认文件对象.

struct.Struct需要明确指定填充字节(x):

"""
struct { double v; int t; char c;};
"""
from struct import Struct

x = Struct('dicxxx')
with open('c_structs.bin', 'rb') as file:
    result = []
    while True:
        buf = file.read(x.size)
        if len(buf) != x.size:
            break
        result.append(x.unpack_from(buf))

print(result)
Run Code Online (Sandbox Code Playgroud)

它产生相同的输出.

为避免不必要的复制Array.from_buffer(mmap_file),可以使用从文件中获取结构数组:

import mmap # Unix, Windows
from contextlib import closing

with open('c_structs.bin', 'rb') as file:
    with closing(mmap.mmap(file.fileno(), 0, access=mmap.ACCESS_COPY)) as mm: 
        result = (YourStruct * 3).from_buffer(mm) # without copying
        print("\n".join(map("{0.v} {0.t} {0.c}".format, result)))
Run Code Online (Sandbox Code Playgroud)


per*_*eal 7

一些C代码:

#include <stdio.h>
typedef struct { double v; int t; char c;} save_type;
int main() {
    save_type s = { 12.1f, 17, 's'};
    FILE *f = fopen("output", "w");
    fwrite(&s, sizeof(save_type), 1, f);
    fwrite(&s, sizeof(save_type), 1, f);
    fwrite(&s, sizeof(save_type), 1, f);
    fclose(f);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

一些Python代码:

import struct
with open('output', 'rb') as f:
    chunk = f.read(16)
    while chunk != "":
        print len(chunk)
        print struct.unpack('dicccc', chunk)
        chunk = f.read(16)
Run Code Online (Sandbox Code Playgroud)

输出:

(12.100000381469727, 17, 's', '\x00', '\x00', '\x00')
(12.100000381469727, 17, 's', '\x00', '\x00', '\x00')
(12.100000381469727, 17, 's', '\x00', '\x00', '\x00')
Run Code Online (Sandbox Code Playgroud)

但也存在填充问题.填充大小save_type为16,所以我们再读3个字符并忽略它们.