3

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

谢谢!

4

1 回答 1

3

您所写的内容是合理的,但如果应该只有 56 个字节,那么尝试读取 512 个字节没有任何意义。此外,不要重复 512,而是sizeof(data)用于第二次出现。您可以将代码打包为一个函数,并且在不匹配时打印出实际和预期的校验和。校验和算法不是很敏感,所以它很容易漏掉一些错误,比如转置错误,虽然它也能捕捉到一个公平的数字。


嗯……再看一遍……你写道:

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

由于sumis a (signed) int,您可能应该写:

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

否则,您可能会溢出。也许不仅仅是 54 字节的数据,但如果要校验和的数据足够长(肯定超过 256 字节),您最终可能会得到一个大于 65535 的总和,并且在不应该的情况下比较会失败。我假设sizeof(int) == 4,而不是sizeof(int) == 2

于 2012-04-14T03:25:51.287 回答