将C二进制数据读取函数转换为Python
(为了清楚起见,我编辑了这个,并根据EOL的答案改变了实际问题)
我正在尝试将C中的以下函数转换为 Python但是失败了(参见下面的C代码).据我所知,它需要从from指向的内存位置开始的四个1字节字符,将它们视为无符号长整数以便为每个字节提供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,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,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,176): return True return False 解决方法
啊,我想我已经明白了.请注意,描述说
/* The claim algorithm for Alan files is: * For Alan 3,so check that they're all within the file * Locate the checksum and verify that it is correct */ 我读到的是,Alan 3中有一个神奇的词,但不是Alan 2.但是,你的代码是另一种方式,即使C代码只假定Alan 3文件存在ALAN. 为什么?因为你不会说C,所以你猜对了 – 自然就够了! – memcmp将返回(相当于Python)如果sf和“ALAN”的前四个字符相等,则为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 'x02x08x01x00' >>> alan3 'ALAN' (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |