2012-04-14 102 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