【问题标题】:Converting C's fread to python, not getting expected output将 C 的 fread 转换为 python,没有得到预期的输出
【发布时间】:2015-04-29 06:03:08
【问题描述】:

我正在将一个小程序从 C 转换为 Python,但在读取文件时遇到了问题。它是一个 .dat 文件,其中包含十六进制格式的数据。这是我尝试读取的前 132 个字节

2400 0000 4c61 7a61 726f 2053 756e 6965
7200 ffff 0000 0000 7261 6a70 6f6f 7420
6279 776f 726b 2069 7363 6869 6f70 7562
6963 2073 6872 6f76 6574 6964 6520 6469
7373 7561 5275 746c 616e 642c 5665 726d
6f6e 742c 0d00 0000 7000 0000 0000 0000
0000 0000 0000 0000 4000 0000 0000 0000
ffff ffff 656e 2073 6f76 6572 6f62 6564
6965 6e74

读取这个的 C 代码打开fp 中的文件并像这样读取它。

TEXT_SHORT = 64;

fread(&(record->id), sizeof(int), 1, fp);
fread(&(record->name[0]), sizeof(char), TEXT_SHORT, fp);
fread(&(record->location[0]), sizeof(char), TEXT_SHORT, fp);

printf("%06d\n", record->id);
printf("%s\n", record->name);
printf("%s\n", record->location);

然后在打印值时,我得到这个:

36
Lazaro Sunier
Rutland,Vermont,

为了将此功能转换为 Python,我编写了以下代码:

def read_file(file):
    id = struct.unpack('i', file.read(4))[0]
    name = ''.join(struct.unpack('c'*64, file.read(64)))
    location = ''.join(struct.unpack('c'*64, file.read(64)))
    print(id)
    print(name)
    print(location)

然后我得到这个输出

36
Lazaro Sunier��rajpoot bywork ischiopubic shrovetide dissua
p@����en soverobedient

我已经为此苦苦挣扎了一段时间,不知道为什么会这样。 fread() 做的事情是我需要在 Python 中实现的背景,还是我做错了?

【问题讨论】:

  • 这不会导致您的错误,但在您的name = name = ''.join(struct.unpack('c'*64, file.read(64))) 行中,您可以删除重复的name = 语句之一。
  • 谢谢。那是复制粘贴错误。
  • 尝试打印 repr(name)repr(location) 您的终端可能只是不支持奇怪的字符......真的与 python 无关

标签: python c struct


【解决方案1】:

尽管您在 C 和 Python 中都在读取 64 字节块,但 Python 没有 \x00 这样的东西作为字符串终止符。因此,虽然 C 中的 printf 将打印到第一个 \0,但 Python 将打印整个缓冲区,包括尾随垃圾。

\0处拆分字符串,只保留第一部分:

name = name.split(b"\0", 1)[0]
location = name.split(b"\0", 1)[0]

顺便说一句,您可以在一行中检索 3 个元素:

id, name, location = struct.unpack("i64s64s", file.read(132))
name = name.split(b"\0", 1)[0]
location = name.split(b"\0", 1)[0]

【讨论】:

  • 另外,您可以让 struct 计算要读取的缓冲区的大小:my_struct = struct.Struct("i64s64s")_id, name, location = my_struct.unpack(f.read(my_struct.size))
  • 太棒了!太感谢了。我没有意识到有一个终结者。
  • 只是唠叨...name.split(b"\0", 1)[0] 更快一点,因为它在第一个元素之后停止分裂。
猜你喜欢
  • 2018-10-02
  • 1970-01-01
  • 2020-09-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多