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

2024-09-29 18:52:32 发布

您现在位置:Python中文网/ 问答频道 /正文

我对使用Python很陌生,对C也很生疏,所以我要为自己的声音是多么愚蠢和/或丢失而预先道歉。

我在C中有一个函数,它创建一个包含数据的.dat文件。我正在使用Python打开文件来读取该文件。我需要阅读的内容之一是在C函数中创建并以二进制形式打印的结构。在我的Python代码中,我在文件的适当行中读取结构。我试过一件一件地拆开这张照片,但没有成功。结构中的大多数项在C代码中声明为“real”。我正在和其他人一起编写这段代码,主要的源代码是his,并已将变量声明为“real”。我需要将其放入循环,因为我想读取以“.dat”结尾的目录中的所有文件。要开始循环,我有:

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

然后我阅读了包含结构的那一行之前的所有行。然后我走到那条线上,得到:

      part_struct = part.readline()
      r = struct.unpack('<d8', part_struct[0])

我只是想看看结构中存储的第一个东西。我在这里看到了一个例子。当我试着这样做的时候,我得到了一个错误,上面写着:

struct.error: repeat count given without format specifier

我会接受任何人给我的建议。我已经坚持了几天,尝试了很多不同的事情。老实说,我不理解struct模块,但我已经尽可能多地阅读了它。

谢谢!


Tags: 文件path函数代码in声明forfiles
3条回答

可以使用^{}^{}指定文件的格式。要从C code in @perreal's answer生成的文件中读取结构:

"""
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'), ...]

^{}。它在Python3中受支持,但在Python2.7中没有针对default file object的文档。

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)

它产生相同的输出。

为避免不必要的复制,^{}可用于从文件中获取结构数组:

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)))

格式说明符中的数字表示重复计数,但它必须在字母之前,如'<8d'。不过,您说过只想读取结构的一个元素。我想你只是想'<d'。我想您正在尝试将要读取的字节数指定为8,但不需要这样做。d假设是这样。

我还注意到你在使用readline。读取二进制数据似乎是错误的。它将一直读取,直到下一个回车/换行,这将在二进制数据中随机出现。您要做的是使用read(size),如下所示:

part_struct = part.read(8)
r = struct.unpack('<d', part_struct)

实际上,您应该小心,因为read返回的数据可能少于您的请求。你需要重复一遍。

part_struct = b''
while len(part_struct) < 8:
    data = part.read(8 - len(part_struct))
    if not data: raise IOException("unexpected end of file")
    part_struct += data
r = struct.unpack('<d', part_struct)

一些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;
}

一些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)

输出

(12.100000381469727, 17, 's', '\x00', '\x00', '\x00')
(12.100000381469727, 17, 's', '\x00', '\x00', '\x00')
(12.100000381469727, 17, 's', '\x00', '\x00', '\x00')

但也有填充问题。save_type的填充大小是16,因此我们又读取了3个字符并忽略它们。

相关问题 更多 >

    热门问题