2012-04-14 111 views
3

在C中,读取二进制文件内容并验证校验和的正确方法是什么?C - 读取二进制文件,验证校验和

这里是我正在使用的数据的一个示例:

 
0A 01 17 D8 04 00 07 9A 1F 10 FF CF 7F FF FF FF 
FF 7F 7F 7F FF 7F FF FF FF FF 7F 81 01 01 03 01 
01 01 01 81 00 73 67 68 66 97 6C 76 64 64 6A 6B 
6E 64 66 67 44 41 [17 7A]

 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 44 41 [00 85]

校验(方括号之间)存储先前54个字节的总和为2字节(大端)编号。

这是我一直使用的是什么:

#include <stdio.h> 
int main(int argc, char **argv) 
{ 
    FILE *f = fopen(argv[1], "rb"); 

    unsigned char data[512]; 
    fread(data, 1, 512, f); 

    int i; 
    int sum = 0; 
    for (i = 0; i < 54; i++) 
    { 
     sum += data[i]; 
    } 

    if ((sum >> 8) == data[54] && 
     (sum & 0xFF) == data[55]) 
    { 
     printf("Checksum is valid.\n"); 
    } 
    else 
    { 
     printf("Checksum is invalid.\n"); 
    } 
    system("pause"); 
} 

我使用了一个字符数组来存储字节,使用索引来重新计算循环校验。为了验证我使用了一些按位移和掩蔽。有更好的解决方案吗?

谢谢!

回答

3

你写的是合理的,但如果应该只有56个字节,试图读取512个字节是没有意义的。另外,不要重复512,请使用sizeof(data)作为第二次出现。您可以将代码打包为函数,并且在出现不匹配时可能会打印出实际和预期的校验和。校验和算法不是非常敏感,所以它很容易错过一些错误,例如错位错误,尽管它也会得到一个合理的数字。


嗯......再......看你写的:

if ((sum >> 8) == data[54] && 
    (sum & 0xFF) == data[55]) 

由于sum是(签字)int,你可能应该写:

if ((sum >> 8) & 0xFF == data[54] && 
    (sum & 0xFF)  == data[55]) 

否则,你可能会发生溢出。也许不是只有54个字节的数据,但如果要进行校验和的数据足够长(肯定超过256个字节),则最终总和可能大于65535,如果不应该,则比较会失败。我假设sizeof(int) == 4,而不是sizeof(int) == 2