导语:
在ARM上或在其他芯片上做开发,有时候会有这样的需求,将你工控机、开发板或者你的设备采集出来的数据做成一个exc列表;最简单的方式就是用数据直接输出为.txt文件,但是这样并不方便wps或者Excel表格打开;
常用的一个方式就是生成.csv文件;这是大多数上位机采取的一种数据存根的方式;对某些场合的使用是非常便利!
接下来总结在ARM板上实现的,对数据生成.csv的操作;其他的平台,方式类同;
1.csv文件生成接口
普及一下:.csv文件格式要求--百度百科https://baike.baidu.com/item/CSV/10739?fr=aladdin
/root__/business (代码位置)
|__/flow (流水位置-有coout索引和.csv文件)
操作过程,一完整的数据到了,先查询上次写入到哪一个文件哪一条流水,比如是第1个文件的第100条(最大数),此次立马写入第2个文件第一条(第0条并补上第0条的标题);如果写到第1个文件的第23条,那么该次流水应该写第1个文件的第24条(不需要补充标题);写完后里面更新文件和流水索引--以便下次查询;
/****************************************************
* 函数名:create_flow
* 功能描述:生成流水
* 输入参数:流水原始的数据
* 输出参数:
* 返回值:
* 备注:
****************************************************/
void VCBusiness::create_flow(const OBU_OBJECT_STRU *obu_object) {
if (NULL == obu_object) {
LOG_ERROR("func:%s : 指针为NULL", __func__);
return;
}
u16 file_index = 0, flow_index = 0;
char file_name[64] = {0};
string write_str;
char write_head[1024] = {0};
char temp[32] = {0};
FILE *fp = NULL;
u16 trans_time = GET_INTERVAL_TIME(obu_object->life_time);
/* 获取索引 */
get_flow_file_index(&flow_index, &file_index);
/* 根据索引指定记录文件 */
sprintf(file_name, "/root/flow/flow_file_%05d.csv", file_index);
/* 打开记录文件 */
fp = fopen(file_name, "a+");
if (NULL == fp) {
LOG_WARN("[%s]打开文件失败", __func__);
return;
}
/* 未记录过文件 */
if (0 == flow_index) {
//sprintf(write_head, "TransResult,ErrorCode,TransTime,TAC,PSAMTradeNum,FlagNo,RsuNo,DevType,ObuId,OBUProvider,ContractType,CPC EF02,OBUSerialNum,OBUStartTime,OBUEndTime,OBUStatus,VehClass,VehPlate,VehPlateColor,CardProvider,CPUCardType,CardVersion,CardNetWork,CardId,CardStartTime,CardEndTime,TerminalId,TotalTime\n");
sprintf(write_head, "TransResult,ErrorCode,TransTime,TAC,PSAMTradeNum,FlagNo,RsuNo,DevType,ObuId,OBUProvider,E-WalletTradeNum ,CPC EF02,OBUSerialNum,OBUStartTime,OBUEndTime,OBUStatus,VehClass,VehPlate,VehPlateColor,CardProvider,CPUCardType,CardVersion,CardNetWork,CardId,CardStartTime,CardEndTime,TerminalId,TotalTime\n");
fwrite(write_head, sizeof(char), strlen(write_head), fp);
}
/********************开始组.csv文件内容**********************************************************************/
bytes_to_hex_string(&write_str, &obu_object->transresult, 1); //保存原来的16进制,直接写入
......
//bytes_to_hex_string(&write_str, obu_object->obu_flow_info.vehicle_info_stru.VehicleLicencePlateColor_Pack, 2);
memcpy(temp, obu_object->obu_flow_info.vehicle_info_stru.VehicleLicencePlateColor_Pack, 2);//对hex转ascii,汉字写入
write_str.append(temp, 2);
memset(temp, 0, sizeof(temp));
sprintf(temp, ","); write_str.append(temp);
......
/* CardEndTime */
bytes_to_hex_string(&write_str, obu_object->obu_flow_info.iccard_info_stru.issuerinfo + 24, 4);
/* TerminalId */
bytes_to_hex_string(&write_str, obu_object->obu_flow_info.trade_info_stru.TerminalID, 6);
/* TotalTime */
sprintf(temp, "%08x\n", trans_time);//最后一个变量,不需要补逗号,直接追加打印
write_str.append(temp);
/*******************组.csv文件内容结束***********************************************************************/
/* 写入文件 */
fwrite(write_str.c_str(), sizeof(char), write_str.length(), fp);
fclose(fp);
/* 更新索引 */
if (flow_index >= FLOW_COUNT_PER_FILE_MAX) {
flow_index = 0;
file_index++;
} else {
flow_index++;
}
set_flow_file_index(flow_index, file_index);
}
2.开头的查询和结尾的更新索引操作
/****************************************************
* 函数名:get_flow_file_index
* 功能描述:获取流水数据的存储索引
* 输入参数:
* 输出参数:file_index-当前流水文件索引, flow_index-单个文件流水索引
* 返回值:
* 备注:避免单文件太大,所以会生成多个文件,故有文件索引号1,2,3,4...
* 备注:为方便浏览和传输,每个文件都存100条流水,故流水索引号1,2..100
****************************************************/
bool VCBusiness::get_flow_file_index(u16 *flow_index, u16 *file_index) {
system("touch /root/flow/countor");//创建文件的个数,为避免单个文件太大
/* 流水文件编号 */
auto file_count = ConfDataParsor::GetValue("FILE_COUNT", flow_countor_path);
if (!file_count.success) {
*file_index = 0;
LOG_DEBUG("[%s][%d]", __func__, __LINE__);
} else {
*file_index = atoi(file_count.data);//获得上次最新的文件索引
}
/* 流水编号 */
auto flow_count = ConfDataParsor::GetValue("FLOW_COUNT", flow_countor_path);
if (!flow_count.success) {
*flow_index = 0;
LOG_DEBUG("[%s][%d]", __func__, __LINE__);
} else {
*flow_index = atoi(flow_count.data);//获得上次产生的最新的流量序号,100条流水打包为一个文件
}
}
/****************************************************
* 函数名:set_flow_file_index
* 功能描述:设置流水存储索引
* 输入参数:file_index-流水文件索引, flow_index-单个文件流水索引
* 输出参数:
* 返回值:
* 备注:
****************************************************/
void VCBusiness::set_flow_file_index(u16 flow_index, u16 file_index) {
system("touch /root/flow/countor");
/* 流水文件编号 */
if (false == ConfDataParsor::SetValue("FILE_COUNT", flow_countor_path, file_index)) {
LOG_WARN("[%s]设置流水文件编号失败", __func__);
}
/* 文件内流水编号 */
if (false == ConfDataParsor::SetValue("FLOW_COUNT", flow_countor_path, flow_index)) {
LOG_WARN("[%s]设置流水编号失败", __func__);
}
}
3.中间的的数据存储说明
//如果是16进制-hex追加的话可以用sprintf(temp, "%02x", data[i]);string->append(temp);
//如果需要追加汉字则需要,sprintf(temp,"黄色");再追加string->append(temp);
//追加逗号是.csv的文件要求
void VCBusiness::bytes_to_hex_string(string *string, const u8 *data, u16 len) {
char temp[10] = {0};
for (int i = 0; i < len; ++i) {
sprintf(temp, "%02x", data[i]);
string->append(temp);
}
sprintf(temp, ",");
string->append(temp);
}
4.最后用wps或excel打开的效果如图-供参考
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)