gpt4 book ai didi

python - 将 C 二进制数据读取函数转换为 Python

转载 作者:太空狗 更新时间:2023-10-29 15:41:19 25 4
gpt4 key购买 nike

(为清楚起见,我对此进行了编辑,并根据 EOL 的回答稍微更改了实际问题)我试图将 C 中的以下函数转换为 Python,但失败得很惨(请参阅下面的 C 代码)。据我了解,它需要四个 1 字节的字符,从 from 指向的内存位置开始,将它们视为无符号长整型,以便为每个字符提供 4 字节的空间,并进行一些位移将它们排列为大端 32 位整数。然后将其用于检查文件有效性的算法。 (来自Treaty of Babel)

static int32 read_alan_int(unsigned char *from)
{
return ((unsigned long int) from[3])| ((unsigned long int)from[2] << 8) |
((unsigned long int) from[1]<<16)| ((unsigned long int)from[0] << 24);
}
/*
The claim algorithm for Alan files is:
* For Alan 3, check for the magic word
* load the file length in blocks
* check that the file length is correct
* For alan 2, each word between byte address 24 and 81 is a
word address within the file, so check that they're all within
the file
* Locate the checksum and verify that it is correct
*/
static int32 claim_story_file(void *story_file, int32 extent)
{
unsigned char *sf = (unsigned char *) story_file;
int32 bf, i, crc=0;
if (extent < 160) return INVALID_STORY_FILE_RV;
if (memcmp(sf,"ALAN",4))
{ /* Identify Alan 2.x */
bf=read_alan_int(sf+4);
if (bf > extent/4) return INVALID_STORY_FILE_RV;
for (i=24;i<81;i+=4)
if (read_alan_int(sf+i) > extent/4) return INVALID_STORY_FILE_RV;
for (i=160;i<(bf*4);i++)
crc+=sf[i];
if (crc!=read_alan_int(sf+152)) return INVALID_STORY_FILE_RV;
return VALID_STORY_FILE_RV;
}
else
{ /* Identify Alan 3 */
bf=read_alan_int(sf+12);
if (bf > (extent/4)) return INVALID_STORY_FILE_RV;
for (i=184;i<(bf*4);i++)
crc+=sf[i];
if (crc!=read_alan_int(sf+176)) return INVALID_STORY_FILE_RV;

}
return INVALID_STORY_FILE_RV;
}

我正在尝试用 Python 重新实现它。为了实现 read_alan_int 函数,我认为导入 struct 并执行 struct.unpack_from('>L', data, offset) 会起作用.但是,对于有效文件,这总是为值 bf 返回 24,这意味着 for 循环被跳过。

def read_alan_int(file_buffer, i):
i0 = ord(file_buffer[i]) * (2 ** 24)
i1 = ord(file_buffer[i + 1]) * (2 ** 16)
i2 = ord(file_buffer[i + 2]) * (2 ** 8)
i3 = ord(file_buffer[i + 3])
return i0 + i1 + i2 + i3

def is_a(file_buffer):
crc = 0
if len(file_buffer) < 160:
return False
if file_buffer[0:4] == 'ALAN':
# Identify Alan 2.x
bf = read_alan_int(file_buffer, 4)
if bf > len(file_buffer)/4:
return False
for i in range(24, 81, 4):
if read_alan_int(file_buffer, i) > len(file_buffer)/4:
return False
for i in range(160, bf * 4):
crc += ord(file_buffer[i])
if crc != read_alan_int(file_buffer, 152):
return False
return True
else:
# Identify Alan 3.x
#bf = read_long(file_buffer, 12, '>')
bf = read_alan_int(file_buffer, 12)
print bf
if bf > len(file_buffer)/4:
return False
for i in range(184, bf * 4):
crc += ord(file_buffer[i])
if crc != read_alan_int(file_buffer, 176):
return False
return True
return False


if __name__ == '__main__':
import sys, struct
data = open(sys.argv[1], 'rb').read()
print is_a(data)

...但该死的东西仍然返回 24。不幸的是,我的 C 技能不存在,所以我无法让原始程序打印一些调试输出,所以我可以知道 bf 应该是什么。

我做错了什么?


好的,我显然正确地执行了 read_alan_int。但是,对我来说失败的是检查前 4 个字符是否为“ALAN”。我所有的测试文件都未通过此测试。我更改了代码以删除此 if/else 语句并改为仅利用早期返回,现在我的所有单元测试都通过了。所以,在实际层面上,我完成了。但是,我会保留这个问题以解决新问题:我怎样才能从前 4 个字符中提取“ALAN”呢?

def is_a(file_buffer):
crc = 0
if len(file_buffer) < 160:
return False
#if file_buffer.startswith('ALAN'):
# Identify Alan 2.x
bf = read_long(file_buffer, 4)
if bf > len(file_buffer)/4:
return False
for i in range(24, 81, 4):
if read_long(file_buffer, i) > len(file_buffer)/4:
return False
for i in range(160, bf * 4):
crc += ord(file_buffer[i])
if crc == read_long(file_buffer, 152):
return True
# Identify Alan 3.x
crc = 0
bf = read_long(file_buffer, 12)
if bf > len(file_buffer)/4:
return False
for i in range(184, bf * 4):
crc += ord(file_buffer[i])
if crc == read_long(file_buffer, 176):
return True
return False

最佳答案

啊,我想我明白了。请注意,描述说

/*
The claim algorithm for Alan files is:
* For Alan 3, check for the magic word
* load the file length in blocks
* check that the file length is correct
* For alan 2, each word between byte address 24 and 81 is a
word address within the file, so check that they're all within
the file
* Locate the checksum and verify that it is correct
*/

我读到的意思是 Alan 3 中有一个神奇的词,但 Alan 2 中没有。但是,您的代码是相反的,即使 C 代码仅假定 ALAN 存在于 Alan 3 文件中。

为什么?因为你不会说C,所以你猜——自然够了! -- 如果 sf 和“ALAN”的前四个字符相等,memcmp 将返回(相当于 Python)True。但事实并非如此。 memcmp returns 0如果内容相等,如果内容不同则非零。

这似乎是它的工作方式:

>>> import urllib2
>>>
>>> alan2 = urllib2.urlopen("http://ifarchive.plover.net/if-archive/games/competition2001/alan/chasing/chasing.acd").read(4)
>>> alan3 = urllib2.urlopen("http://mirror.ifarchive.org/if-archive/games/competition2006/alan/enterthedark/EnterTheDark.a3c").read(4)
>>>
>>> alan2
'\x02\x08\x01\x00'
>>> alan3
'ALAN'

关于python - 将 C 二进制数据读取函数转换为 Python,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7137613/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com