C语言如何将海量整数存入数据文件且不占用过多磁盘空间
可行优化方案
你的数据只有1、-1两种取值,信息熵极低,当前用fprintf写文本格式int的方案存在极大空间冗余,可按下面的方案按需选择,最高能把存储空间降到原体积的1/10甚至更低。
1. 位打包存储(零依赖、速度最快,理论最优基础存储)
每个元素仅需1bit即可表示:约定1对应数值1,0对应数值-1,每8个元素打包为1个unsigned char类型的字节写入文件。
- 空间测算:1e11个元素仅需 1e11 / 8 ≈ 12.5GB 存储空间,相比当前50GB的体积直接减少75%
- 实现逻辑非常简单,不需要引入任何第三方库,二进制读写速度比
fprintf写文本快10倍以上 - 注意事项:需要在文件开头固定写入8字节的数组总长度元数据,避免数组长度不是8的倍数时,最后一个打包字节读出无效位
参考写入代码:
unsigned char cur_pack = 0; int bit_offset = 0; long long total_len = /* 填入当前扫描轮次的数组总长度 */; // 先写入数组总长度作为元数据 fwrite(&total_len, sizeof(long long), 1, fp); for (long long i = 0; i < total_len; i++) { if (arr[i] == 1) { cur_pack |= 1U << bit_offset; } bit_offset++; if (bit_offset == 8) { fwrite(&cur_pack, 1, 1, fp); cur_pack = 0; bit_offset = 0; } } // 写入剩余不满8位的最后一个数据包 if (bit_offset > 0) { fwrite(&cur_pack, 1, 1, fp); }
读取时按元数据的总长度反向解包即可。
2. 位打包+轻量压缩(速度与压缩比平衡)
如果你的模拟数据存在一定规律(比如连续出现相同值、有固定模式),可以在位打包的基础上再加一层轻量压缩,进一步缩小体积:
- 优先选LZ4算法:压缩、解压速度和原生内存拷贝接近,几乎不会拖慢模拟程序的运行效率,对位打包的二进制数据通常能再压缩30%70%,最终总存储体积可降到4GB8GB
- 追求更高压缩比可选择Zstandard算法:高压缩等级下对规律性模拟数据的压缩比更高,仅压缩速度比LZ4稍慢,解压速度依然很快
注意不要直接对原始文本或int数组做压缩,先做位打包再压缩,压缩速度和压缩比都会有明显提升。
3. 游程编码(适配连续重复值极多的场景)
如果你的数据经常出现长段连续相同值(比如连续几十上百个1/-1连续出现),可以直接用游程编码存储:不需要逐位存元素,只需要记录「数值 + 连续出现的长度」的数对即可。比如连续出现2000个1,仅需要存(1, 2000)这一组值。如果数据平均连续重复长度超过8,这个方案的空间占用比纯位存储更低,读写速度也更快。
避坑提醒:不要继续用文本格式存储这类数值数据,文本格式下每个"-1"需要2个字符、每个"1"需要1个字符,再加空格/换行等分隔符,平均每个元素要占2~3字节,不仅空间浪费大,格式转换的IO开销也远高于二进制写入。
内容的提问来源于stack exchange,提问作者Sara Awwad
相关产品推荐
相关产品推荐

