怎么对一个大文件分块求crc校验值

zhanglidn013 2016-11-17 09:37:55
请教一个问题?现在有一个比较大的文件,分块存储在了两个不同的地方,如何计算整个文件的CRC值呢?
怎么对一个大文件分块求crc校验值?
...全文
1355 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
FancyMouse 2017-04-29
  • 打赏
  • 举报
回复
自己把多个文件并在一个流里也行。单独(用同一个多项式)做CRC然后合并起来也行(衔接点需要多做log(文件大小)的计算)。取决于使用场景。
vnvlyp 2017-04-29
  • 打赏
  • 举报
回复
引用 4 楼 calen_ 的回复:
英特尔处理器上有个 _mm_crc32_u32 ,楼主可以去研究一下,据说这一条指令只需要4个周期。 理论上来说所有计算crc的算法都是分块的,把前一块的crc与后一块的前32位xor,然后正常地去算后一块,结果就是连起来的。
SSE4.2的CRC32和有些不一样吧
calen_ 2016-11-26
  • 打赏
  • 举报
回复
英特尔处理器上有个 _mm_crc32_u32 ,楼主可以去研究一下,据说这一条指令只需要4个周期。 理论上来说所有计算crc的算法都是分块的,把前一块的crc与后一块的前32位xor,然后正常地去算后一块,结果就是连起来的。
「已注销」 2016-11-23
  • 打赏
  • 举报
回复
最后一个少了 CRC32_Final(&ctx, crc32);
「已注销」 2016-11-23
  • 打赏
  • 举报
回复
http://bbs.csdn.net/topics/391807382 看我的 #5 回复。一般这类计算 hash 的都会由一个 Init、Update、Final 函数。你只需要多次调用 Update 即可将大数据分块计算。举例如下:
unsigned char crc32[4] = { 0 };
const unsigned char crcBuff[] = "abcdef";

// 以下三种形式计算 abcdef 字符串结果相同
CRC32_CTX ctx = { 0 };

CRC32_Init(&ctx);
// 分块计算
CRC32_Update(&ctx, &crcBuff[0], 2);
// 分块计算
CRC32_Update(&ctx, &crcBuff[2], 2);
// 分块计算
CRC32_Update(&ctx, &crcBuff[4], 2);
CRC32_Final(&ctx, crc32);

printf("%02X%02X%02X%02X\n", crc32[0], crc32[1], crc32[2], crc32[3]);

CRC32_Init(&ctx);
// 分块计算
CRC32_Update(&ctx, &crcBuff[0], 4);
// 分块计算
CRC32_Update(&ctx, &crcBuff[4], 2);
CRC32_Final(&ctx, crc32);

printf("%02X%02X%02X%02X\n", crc32[0], crc32[1], crc32[2], crc32[3]);

CRC32_Init(&ctx);
// 分块计算
CRC32_Update(&ctx, &crcBuff[0], 6);

printf("%02X%02X%02X%02X\n", crc32[0], crc32[1], crc32[2], crc32[3]);
赵4老师 2016-11-17
  • 打赏
  • 举报
回复
仅供参考:
#include <sys\stat.h>
#include <io.h>
#include <fcntl.h>
#include <share.h>
#include <stdlib.h>
#include <stdio.h>
#include <conio.h>
#include <string.h>
#define MAX_CLU_BYTES 65536
FILE *fo;
int fh;
__int64 offs,offs1;
__int64 rvi64;
int rv,wrv;
unsigned char buf[MAX_CLU_BYTES];
char ofn[_MAX_PATH];
char offstr[80];
char drive[_MAX_DRIVE];
char dir[_MAX_DIR];
char fname[_MAX_FNAME];
char ext[_MAX_EXT];
char fullpath[_MAX_PATH];
void strcpybutcomma(char *t,char *s) {
    char c;

    while (1) {
        c = *s++;
        if (','!=c) *t++ = c;
        if (0==c) break;
    }
}
int main(int argc,char **argv) {
    if (argc<3) {
        printf("Copy File Tail.\n");
        printf("Usage:\n");
        printf("    cft filename.ext {Offset_Begin|-Offset_End|Offset_Begin-Offset_End}\n");
        printf("Copy filename.ext {OB|-OE|OB-OE} to {OB|~OE|OB-OE}-filename.ext\n");
        printf("Note: Byte at OE is NOT included.\n");
        printf("Example:\n");
        printf("    cft abc.rar 12345\n");
        printf("Copy abc.rar offset 12345-end to 12345-abc.rar\n");
        printf("    cft abc.rar -12345\n");
        printf("Copy abc.rar offset -12345-end to ~12345-abc.rar\n");
        printf("    cft abc.rar 123-12345\n");
        printf("Copy abc.rar offset 123-12345 to 123-12345-abc.rar\n");
        printf("    cft abc.rar 0xAB-0xCD\n");
        printf("Copy abc.rar offset 0xAB-0xCD to 0xAB-0xCD-abc.rar\n");
        return 1;
    }
    strcpybutcomma(offstr,argv[2]);
    rv=sscanf(offstr,"%I64i-%I64i",&offs,&offs1);
    if (rv==0) {
        printf("offset %s is not number\n",argv[2]);
        return 2;
    }
    if (NULL==_fullpath(fullpath,argv[1],_MAX_PATH)) {
        printf("Can not get fullpath of %s\n",argv[1]);
        return 10;
    }
    fh=_sopen(fullpath,_O_BINARY|_O_RDONLY|_O_RANDOM,_SH_DENYNO);
    if (fh==-1) {
        printf("_sopen %s errno=%d %s\n",fullpath,errno,strerror(errno));
        return 3;
    }
    if (rv==1) {
        offs1=_filelengthi64(fh);
        if (offs1==-1i64) {
            printf("%I64d=_filelengthi64 errno=%d %s\n",offs1,errno,strerror(errno));
            _close(fh);
            return 4;
        }
        if (offs<0i64) {
            offs=offs1+offs;
            if (offs<0i64) offs=0i64;
        }
    } else {//rv==2
        if (offs>offs1) {
            printf("%s offset_begin %I64d > %I64d offset_end error\n",argv[2],offs,offs1);
            _close(fh);
            return 5;
        }
    }
    rvi64=_lseeki64(fh,offs,SEEK_SET);
    if (rvi64!=offs) {
        printf("%I64d=_lseeki64 %I64d errno=%d %s\n",rvi64,offs,errno,strerror(errno));
        _close(fh);
        return 6;
    }
    _splitpath(fullpath,drive,dir,fname,ext);
    if (offstr[0]=='-') offstr[0]='~';
    sprintf(ofn,"%s%s%s-%s%s",drive,dir,offstr,fname,ext);
    fo=fopen(ofn,"wb");
    if (fo==NULL) {
        printf("fopen %s errno=%d %s\n",ofn,errno,strerror(errno));
        _close(fh);
        return 7;
    }
    cprintf("\n%I64d\r",offs);
    while (1) {
        rv=_read(fh,buf,(unsigned int)__min(offs1-offs,MAX_CLU_BYTES));
        if (rv==0) break;//
        if (rv<0) {
            printf("_read %s offset %I64d errno=%d %s\n",fullpath,offs,errno,strerror(errno));
            fclose(fo);
            _close(fh);
            return 8;
        }
        wrv=fwrite(buf,1,rv,fo);
        if (wrv!=rv) {
            printf("fwrite %s errno=%d %s\n",ofn,errno,strerror(errno));
            fclose(fo);
            _close(fh);
            return 9;
        } else {
            offs+=rv;
            cprintf("%I64d\r",offs);
            if (offs>=offs1) break;//
        }
    }
    fclose(fo);
    _close(fh);
    printf("Copy %s offset %s to %s OK.\n",fullpath,argv[2],ofn);
    return 0;
}
至于CRC相关代码,参考7zip源代码相关片断。
QuickEncrypt,数据安全小工具,采用托盘图标、悬浮窗、鼠标拖拽、右键菜单的简单操作模式,提供文件、文本的加解密(RC4+AES)、Hash(MD5+SHA1)、安全擦除等功能。独有的“智能压缩”加密模式。 1.功能介绍 对鼠标拖入的文本进行加解密 对剪贴板中的文本进行加解密 对鼠标拖入的文件进行加解密 对鼠标拖入的文件进行擦除 对鼠标拖入的文本进行Hash计算 对剪贴板中的文本进行Hash计算 对鼠标拖入的文件进行Hash计算 针对文本和文件加解密的智能数据压缩技术 支持超过4GB的大文件 2.安全机制 2.1 文件擦除策略 a.修改文件名为随机串; b.以32字节的块向文件写入全0; c.刷新数据,关闭文件; d.修改文件名为随机串; e.以32字节的块向文件写入全1; f.刷新数据,关闭文件; g.截断文件大小为0; h.删除文件。 经测试常用数据恢复软件无法成功恢复原有数据。 2.2 Hash算法 使用OpenSSL 0.98提供的MD5(128位)和SHA1(160位)算法。 2.3 加解密密钥生成 将用户输入的密码明文转换成utf-8字节数组(不包含0结束符),计算MD5和SHA1,将MD5结果用作AES 128位密钥,将SHA1结果用作RC4密钥。 2.4 文本加密策略 a.将明文数据转换成utf-8字节数组(包含0结束符); b.对明文字节数组计算CRC32校验码,用于解密时校验,并将CRC32放在明文首字节之前; c.尝试压缩步骤b的结果(zlib level9),若获得较小的压缩结果则输出压缩后的编码数组,否则放弃压缩,直接输出步骤b的结果; d.对步骤c的结果进行RC4流加密(OpenSSL 0.98); e.对步骤d的结果进行AES_CFB_128分组加密(OpenSSL 0.98); f.对步骤e的结果进行Base64编码(OpenSSL 0.98); g.将标记"QE:|"附加在步骤f的结果之前,输出结果。 2.5 文件加密策略 a.判断输入文件的扩展名是否是压缩格式,对常见压缩格式和流媒体编码文件不启用数据压缩功能; b.以1MB大小分块,读入明文文件数据; c.对分块的明文数据计算MD5,附加在待加密数据之前,用于解密时校验; d.尝试压缩1MB大小的分块,若获得较小的压缩结果则输出压缩后的编码数据,否则直接输出原文; e.对步骤d的结果进行RC4流加密(OpenSSL 0.98); f.对步骤e的结果进行AES_CFB_128分组加密(OpenSSL 0.98); g.将分块数据依次写入输出文件,输出文件文件名是在原文件名后加".enc"。

69,373

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧