C语言获取文件CRC32值

Category: 代码片段 | Tags: c语言, crc32 | Source: Markdown ----------> Back to Wiki

这是一段获取文件CRC32值的代码,与WinRARCRC32值相同。

#include <stdio.h>
#include <stddef.h>
#include <stdint.h>
#include <string.h>

#define CRC32_POLY 0xEDB88320U

typedef struct crc32_handle {
    uint32_t table[256];
    uint32_t crc32;
    uint32_t init;
} CRC32_Handle;

static void crc32_init(CRC32_Handle *handle, uint32_t init) {
    size_t i = 0, j = 0;

    for (i = 0; i < 256; i++) {
        handle->table[i] = i;
        for (j = 0; j < 8; j++) {
            if (handle->table[i] & 0x00000001U)
                handle->table[i] = (handle->table[i] >> 1) ^ CRC32_POLY;
            else
                handle->table[i] = handle->table[i] >> 1;
        }
    }

    handle->crc32 = handle->init = init;
}

static void crc32_update(CRC32_Handle *handle, const uint8_t *buf, size_t len) {
    handle->crc32 ^= 0xFFFFFFFFU;

    while (len--)
        handle->crc32 = (handle->crc32 >> 8) ^ handle->table[(uint8_t)(handle->crc32) ^ *buf++];

    handle->crc32 ^= 0xFFFFFFFFU;
}

static inline void crc32_fetch(CRC32_Handle *handle, uint32_t *crc32) {
    *crc32 = handle->crc32;
    handle->crc32 = handle->init;
}

int main(int argc, char **argv) {
    if (argc != 2) {
        printf("Usage: %s <file>\n", argv[0]);
        return 1;
    }

    FILE *fd = fopen(argv[1], "rb");
    if (fd == NULL) return 1;

    CRC32_Handle handle;
    uint8_t buf[0x00100000U];
    size_t len = 0, i = 0;
    uint32_t crc32 = 0;

    crc32_init(&handle, 0);
    while ((len = fread(buf, sizeof(uint8_t), sizeof(buf), fd)) > 0)
        crc32_update(&handle, buf, len);
    crc32_fetch(&handle, &crc32);

    printf("%08x\n", crc32);
    fclose(fd);

    return 0;
}