利用C一种最有效的文件存储方式——16bit有符号位2进制存储
Posted sunguiy
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了利用C一种最有效的文件存储方式——16bit有符号位2进制存储相关的知识,希望对你有一定的参考价值。
2020年7月6日 23:17:31
环境:VS2013 C语言
最近在处理一些较大的数据,今天想要将一组超过百G的信号采集数据进行信号处理后,在重新存储起来,作为后续程序的起始数据。
在看了网上诸多的什么比如用类人算的方法将整数拆解为2进制、直接存储整数格式等建议之后,我感觉这些都不是我想要的。
受到读取数据16bit有符号数据的启发:(如下,小端模式)
我也想将存储的数据也得到类似于此的性能,即存储数据的大小SizeF严格遵循
SizeF = 2(Byte)* Fs * t
其中Fs为采样率,t为采样时间。
但是使用整形数据直接储存或16进制直接储存并不能满足。
最后我将本问题的解决方案定为:也就是想要读取一组格式为小端模式的16bit有符号数据,并将其进行信号处理后,重新以最有效的16bit有符号数据格式存储(大端模式)起来。。最后也实现了。
一开始的测试,用了一个大小(393750kB)的原数据做例子:
以上为测试的结果,从上到下分别以5位整数(%5d)、4位16进制(%04x)以及16位2进制的不同方式存储。
可以很明显的看出存储方式对空间利用的优化。
其实实现的代码也很简单:
对小端模式的16bit读取重组(作者电脑C以大端模式读取数据),代码如下:
int tek_read(int i_offset, long long int offset, int readSum) { FILE *odata = NULL; char *obuf = NULL; size_t bytes_read; //int16_t mid_data[DATA_BUF_SIZE]; int16_t *mid_data; mid_data = (int16_t *)calloc((2 * readSum), sizeof(int16_t)); int16_t temp = 0x00ff; int16_t temp1 = 0x0000; //用来屏蔽污染中间变量,详情见下 int i, j, l; int d, length = 0; int flag = 10; if (mid_data == NULL) { return FAILURE; } odata = fopen(DATA_name, "r+"); if (odata == NULL) { free(mid_data); return FAILURE; } obuf = (char *)malloc((readSum * 2) * sizeof(char)); //动态分配内存 储存连续readSum *16b 数据 if (obuf == NULL) { free(mid_data); free(obuf); return FAILURE; } long long int t_offset; t_offset = i_offset * offset * 2; flag = _fseeki64(odata, t_offset, 0); bytes_read = fread(obuf, 1, (2 * readSum), odata); fclose(odata); if (bytes_read < (2 * readSum + 1)) { for (i = 0; i < (2 * readSum); i++) { mid_data[i] = obuf[i]; } memset(Iri_data, 0, (2 * readSum)); //将Iri_data元素换成0 for (j = 0; j < readSum; j++) { Iri_data[j] = mid_data[2 * j + 1]; Iri_data[j] <<= 8; temp1 = mid_data[2 * j] & temp; //某些低8位(类型是16位)的前8位读成ff导致或运算之后最终前8位成为ff, //为避免污染,先与0x00ff与运算 Iri_data[j] |= temp1; } free(obuf); //读到Iri_data中后就释放内存 //数组长度 d = 0; l = 0; //可能有连续5个0????末尾是0导致的问题 free(mid_data); //释放中间内部 return length; } else { printf("* I am sorry to tell u there is a trouble in taking Tektronix DATA! Please cheak your settings! "); free(mid_data); //释放中间内存 return 0; } }
中间的信号处理就不详细介绍了
最后的大端模式将16bit有符号数据写入文件,实现代码:
int outfile(void) { FILE *fp_out; fp_out = fopen(outname, "a+"); for (int i = 0; i < length_90ms_7Mhz; i++) { int16_t temp = Iridium_result_D16[i]; //大端模式 fputc((temp >> 8) & 0xFF, fp_out); fputc(temp & 0xFF, fp_out); } fclose(fp_out); return SUCCESS; }
对于我200个G的原始数据,预处理效果很理想。
存储数据效果如下:
以上是关于利用C一种最有效的文件存储方式——16bit有符号位2进制存储的主要内容,如果未能解决你的问题,请参考以下文章
Java -- 每日一问:Java有几种文件拷贝方式?哪一种最高效?
Java -- 每日一问:Java有几种文件拷贝方式?哪一种最高效?