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

2024-05-29 01:56:35 发布

您现在位置: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并执行{}就可以了。但是,对于有效文件,对于值bf,它总是返回24,这意味着跳过for循环。

^{pr2}$

…但那该死的东西还是24小时。很遗憾,我的原版程序不可能打印出来。

我做错什么了?


好吧,所以我很明显读错了。然而,对我来说失败的是检查前4个字符是“艾伦”。我所有的测试文件都没有通过这个测试。我修改了代码,删除了这个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

Tags: forreadreturnifbuffersflongfile
3条回答

假设1:你在Windows上运行,你没有以二进制模式打开文件。在

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

/*
  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
*/

我读到的意思是艾伦3中有个神奇的词,但艾伦2中没有。然而,您的代码则相反,即使C代码只假设alan3文件存在ALAN。在

为什么?因为你不会说C,所以你猜得很自然!如果sf和ALAN的前四个字符相等,那么memcmp将返回True(相当于Python)。。但不是这样。如果内容相等,memcmp returns 0如果内容不同,则非零。在

这似乎就是它的工作方式:

^{pr2}$

你的Python版本在我看来不错。在

PS:我错过了DSM找到的“memcmp()catch”,因此if memcmp(…)…的Python代码实际上应该是`if file_buffer[0:4]!=“艾伦”。在

从C代码和您在对原始问题的注释中给出的示例文件中可以看出,示例文件确实无效;以下是值:

read_alan_int(sf+12) == 24  # 0, 0, 0, 24 in file sf, big endian
crc = 0
read_alan_int(sf+176) = 46  # 0, 0, 0, 46 in file sf, big endian

所以,crc != read_alan_int(sf+176),确实如此。在

您确定样本文件是有效文件吗?或者原始帖子中缺少crc计算的一部分??在

相关问题 更多 >

    热门问题