工程中常需要将数据保存为二进制文件格式,暂以float类型为例,本文分别采用C/C++和python实现二进制文件的保存与读取。
float满足IEEE754标准,故较为直观的方式是每32bit采用IEEE754标准计算,本文采用较为简单的方式实现该功能。
C
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define float_size sizeof(float)
#define char_size sizeof(char)
struct floatArray{
float* fData; // float数组
int fLen; // 数组长度
};
/************** 写文件 **************/
void saveasBin(struct floatArray float_eg, char* fileDir){
FILE *pFile = fopen(fileDir, "wb+");
for(int i = 0; i < float_eg.fLen; i++){
fwrite(&float_eg.fData[i], float_size, 1, pFile);
}
fclose(pFile);
}
/************** 读文件 **************/
// 采用共享内存方式实现类型转换
union IEEE754{
float fValue;
char HValue[4];
};
struct floatArray getData(char* fileDir){
FILE* fp = fopen(fileDir, "rb");
fseek(fp, 0L, SEEK_END);
int fileSize = ftell(fp); // 数据大小
fseek(fp, 0L, SEEK_SET);
char* fStr = (char*)malloc(fileSize*char_size);
memset(fStr, 0, fileSize*char_size);
fread(fStr, fileSize, 1, fp);
fclose(fp);
union IEEE754 c2f;
struct floatArray float_eg_array;
float_eg_array.fLen = fileSize/4;
float_eg_array.fData = (float*)malloc(float_eg_array.fLen*float_size);
memset(float_eg_array.fData, 0, float_eg_array.fLen*float_size);
for (int i = 0; i < float_eg_array.fLen; i++){
c2f.HValue[0] = fStr[4*i];
c2f.HValue[1] = fStr[4*i+1];
c2f.HValue[2] = fStr[4*i+2];
c2f.HValue[3] = fStr[4*i+3];
float_eg_array.fData[i] = c2f.fValue;
}
free(fStr);
return float_eg_array;
}
c++
#include<iostream>
#include<fstream>
#include<vector>
std::vector<float> getSignal(std::string frameBinDir){
std::vector<float> fDataBuff(2000000); // 申请空间,应足够大
std::ifstream infile(frameBinDir.c_str(), std::ifstream::binary);
infile.read((char*)&fDataBuff.front(), fDataBuff.size()*sizeof(float));
int num_tx_samps = infile.gcount()/sizeof(float);
fDataBuff.erase(fDataBuff.begin()+num_tx_samps, fDataBuff.end()); // 清除多余空间
return fDataBuff;
}
python
import struct
import os
def saveasBin(data, fmt, filestr):
"""
@description : 写二进制文件
@param data : 数据
@param fmt : 数据类型
@param fileDir: 写文件地址
"""
with open(filestr, 'wb+') as fp:
for i in data:
fp.write(struct.pack(fmt,i))
def readfromBin(fmt, fileDir):
"""
@description : 读二进制文件
@param fileDir: 读文件地址
@param fmt : 数据类型
@return : 读完文件转换为指定数据类型后的数组
"""
if(fmt in ['b', 'B', 'c']):
n = 1
elif(fmt in ['h', 'H']):
n = 2
elif(fmt in ['f', 'i', 'I', 'l', 'L']):
n = 4
elif(fmt == 'd'):
n = 8
else:
raise ValueError("Please input a right 'fmt' value!\nIt should be in ['b', 'B', 'c', 'd', 'f', 'h', 'H', 'i', 'I', 'l', 'L']!!!")
with open(fileDir, 'rb') as fp:
bytesN = int(os.path.getsize(fileDir)/n)
return struct.unpack(fmt*bytesN, fp.read(bytesN*n))