C - 读取二进制文件,验证校验和

时间:2012-04-14 03:20:19

标签: c binaryfiles checksum code-assist

在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");
}

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

谢谢!

1 个答案:

答案 0 :(得分: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