You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C语言如何分块读取二进制文件并覆盖数据实现大文件加密

低内存环境下C语言分块加密覆盖原文件实现方案

核心实现要点

  • 打开待修改文件必须使用"rb+"读写模式:该模式不会清空原文件,支持读取后回写覆盖指定位置数据;严禁使用"wb"/"wb+"模式,这类模式打开时会直接清空全部文件内容,也不要用只读的"rb"模式,只读模式无法写入数据。
  • 绝对不能用strlen()处理二进制读取的缓冲:文件二进制内容中大概率出现0x00字节,strlen()碰到该字节会直接终止计算,会导致长度统计错误、数据漏加密、内存越界访问等问题,必须使用fread()的返回值获取每次读取到的实际块长度。
  • 分块处理逻辑:每次读取固定大小的缓冲区数据,加密完成后将文件指针移回本次读取块的起始位置,把加密后的数据写回覆盖原内容,再移动指针到下一块起始位置继续读取,全程仅占用缓冲区大小的内存,哪怕文件大小远大于物理内存也能正常处理。
  • 缓冲区大小建议设为4KB-64KB区间,和老旧机械硬盘的扇区/系统页大小对齐,读写效率最高,你机器只有512MB内存,不要把缓冲区设到1MB以上,避免内存分配失败。
  • 你原代码里的无分支密钥索引逻辑本身没有问题,但要提前判断密钥长度不能为0,避免数组越界。

现有代码问题说明

你目前编写的代码仅完成了文件打开、缓冲区申请的基础步骤,缺少分块读取、加密、回写的核心逻辑,还存在几个明显问题:printa和encrypt函数中滥用strlen()处理二进制数据、文件打开失败后未直接返回、申请的缓冲区内存未释放存在泄漏、没有处理文件指针偏移逻辑。另外原加密逻辑用加法做变换的可逆性较差,示例代码里改成了更适合简单加密的异或操作,后续你迭代算法时可以直接替换加密函数内部逻辑,分块框架不需要改动。

修正后可运行代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef unsigned char byte;

// 二进制数据打印需传入实际长度,禁止用strlen统计二进制长度
void printa(byte a[], size_t len) {
    printf("[");
    for (size_t i = 0; i < len; i++) {
        printf("%d", a[i]);
        if (i != len - 1) {
            printf(", ");
        }
    }
    printf("]\n");
}

// 传入当前块实际长度、密钥长度,避免越界
int encrypt(byte data[], size_t data_len, byte key[], size_t key_len, int keyi) {
    for (size_t i = 0; i < data_len; i++) {
        // 示例用异或实现简单对称加密,二次调用即可解密;后续迭代算法直接替换此处逻辑即可
        data[i] ^= key[keyi];
        keyi = (keyi + 1) * (keyi < key_len - 1);
    }
    return keyi;
}

void encrypt_file(byte filename[], byte key[], size_t buffer_size) {
    FILE *file = fopen(filename, "rb+");
    if (file == NULL) {
        printf("UNABLE TO OPEN FILE\n");
        return;
    }

    size_t key_len = strlen((const char*)key);
    if (key_len == 0) {
        printf("INVALID KEY\n");
        fclose(file);
        return;
    }

    byte *buff = malloc(buffer_size);
    if (buff == NULL) {
        printf("MEMORY ALLOC FAILED\n");
        fclose(file);
        return;
    }

    size_t read_len;
    long block_end_pos;
    int keyi = 0;
    // 循环读取直到文件末尾
    while ((read_len = fread(buff, 1, buffer_size, file)) > 0) {
        // 记录当前块读取结束后的文件指针位置
        block_end_pos = ftell(file);
        // 加密当前块数据
        keyi = encrypt(buff, read_len, key, key_len, keyi);
        // 将文件指针移回当前块的起始位置
        fseek(file, block_end_pos - read_len, SEEK_SET);
        // 写入加密后的数据覆盖原内容
        fwrite(buff, 1, read_len, file);
        // 将指针移回块末尾,准备读取下一块
        fseek(file, block_end_pos, SEEK_SET);
    }

    // 资源回收
    free(buff);
    fflush(file);
    fclose(file);
    printf("ENCRYPT COMPLETE\n");
}

int main() {
    // 测试前务必备份原文件,避免逻辑错误导致文件损坏
    encrypt_file("test.txt", (byte*)"your_custom_key", 4096);
    return 0;
}

额外注意事项

  • 首次测试务必先备份目标文件,代码逻辑验证通过后再处理正式文件。
  • 示例用的异或加密属于对称加密,用相同密钥对加密后的文件再执行一次相同流程即可完成解密;如果你后续保留加法加密逻辑,解密时需要对应实现减法逆运算。
  • 如果需要更高的鲁棒性,可以在fread、fwrite、fseek调用后增加返回值判断,处理磁盘坏道、读写权限不足等异常情况。
  • 后续迭代加密算法复杂度时,不需要改动分块读写的框架逻辑,只要修改encrypt函数内的变换规则即可,完全适配大文件+低内存的运行环境。

内容的提问来源于stack exchange,提问作者Fun_Dan3

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 19:56:48