2014. 5. 2. 01:04
C/C++
Tuesday, May 23, 2006 [C언어] 비주얼C로, 파일의 CRC32 값 구하기 (빠르고 메모리 점유 없이)제가 몇 년 전에 외국 사이트에서 CRC32 계산 코드를 구했는데, 실제 쓰려고 보니까 실용성에 문제가 있었습니다. 파일을 메모리에 모두 읽어들인 후에 계산하는 것이었습니다. 그래서 만약 700메가짜리 CD 이미지 파일의 CRC32를 구하려면 메모리가 700메가나 필요했습니다. D:\Z>getcrc "Merriam-Webster Collegiate's Dictionary.iso" A745B2FE: Merriam-Webster Collegiate's Dictionary.iso D:\Z>getcrc Merriam-Webster Collegiate's Dictionary.iso Cannot open input file. D:\Z> 다음의 소스 파일 2개를 getCRC.cpp // 프로그램 본체 CRC32.cpp // CRC32 알고리즘 라이브러리 같은 디렉토리에 넣고 cl getCRC.cpp 이런 명령으로 컴파일하면 됩니다. 다음 창은 cl getCRC.cpp 로 컴파일함과 동시에, 컴파일된 파일에 옵션을 주어 한꺼번에 실행시키는 장면입니다. D:\Z>cl getCRC.cpp & getCRC 0.htm Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 13.10.3077 for 80x86 Copyright (C) Microsoft Corporation 1984-2002. All rights reserved. getCRC.cpp Microsoft (R) Incremental Linker Version 7.10.3077 Copyright (C) Microsoft Corporation. All rights reserved. /out:getCRC.exe getCRC.obj 24531DE5: 0.htm D:\Z> 0.htm 이라는 파일의 CRC32 값인 24531DE5 가 즉시 계산되었습니다. 소스 코드: getCRC.cpp#include <stdio.h> #include <stdlib.h> #include "CRC32.cpp" void help(void); void error(int); int main(int argc, char *argv[]) { FILE *in; if (argc == 1) help(); if( (in = fopen(argv[1], "rb")) == NULL) error(1); printf("%08lX: %s\n", getFileCRC(in), argv[1]); fcloseall(); return 0; } void help(void) { printf("\n\tGet the CRC32 of a given file\n\n\tUsage: this_program_name <file_name>\n"); exit(1); } void error(int number) { switch (number) { case 1 : fputs("Cannot open input file.\n", stderr); break; } exit(number); } 소스 코드: CRC32.cppunsigned long getFileCRC(FILE *); unsigned long calcCRC (const unsigned char *, signed long, unsigned long); void makeCRCtable(unsigned long *, unsigned long); unsigned long getFileCRC(FILE *s) { unsigned char buf [32768]; unsigned long CRC = 0; size_t len; while ( (len = fread(buf, 1, sizeof(buf), s)) != NULL ) CRC = calcCRC(buf, (unsigned long) len, CRC); return CRC; } unsigned long calcCRC(const unsigned char *mem, signed long size, unsigned long CRC) { unsigned long table[256]; CRC = ~CRC; makeCRCtable(table, 0xEDB88320); while(size--) CRC = table[(CRC ^ *(mem++)) & 0xFF] ^ (CRC >> 8); return ~CRC; } void makeCRCtable(unsigned long *table, unsigned long id) { unsigned long i, j, k; for(i = 0; i < 256; ++i) { k = i; for(j = 0; j < 8; ++j) { if (k & 1) k = (k >> 1) ^ id; else k >>= 1; } table[i] = k; } } 벤치마크 4NT의 timer 명령으로 위의 프로그램의 속도를 측정해 보았습니다 (4NT가 설치되어 있어야 함): [1] D:\Warehouse\My Virtual Machines>timer & getcrc "Windows 2000 Professional + MSO [v5.5].zip" & timer Timer 1 on: 3:37:29p 6B517356: Windows 2000 Professional + MSO [v5.5].zip Timer 1 off: 3:37:49p Elapsed: 0:00:19.83 [0] D:\Warehouse\My Virtual Machines> 782MB (820,136,835 바이트) 라는 큰 파일인데도, 불과 20초가 걸렸습니다. 엄청난 속도입니다. 관련 게시물: [QnA] ZIP 이나 RAR 파일의, CRC32 란 무엇입니까? / 'CRC 에러'란? / CRC 값을 어떻게 구하나요? |