使用意图:
用于方便实现包含充电信息的结构体输入到文件中,然后需要的时候,从文件中以充电信息的结构体的形式输出;
简要介绍:
cJSON的使用,网上有很多的资料,主要就是两个文件,一个头文件cJSON.h,一个应用文件cJSON.c,前者主要是对cJSON.c的一些函数的声明,我们在自己的应用程序中,比如main.c中,包含cJSON.h,以及在编译的时候,将cJSON.c和main.c一起编译,即:
这里我用的是:
注:test.c中写入的main函数(c语言编译入口),其中用到的cJSON的应用函数都在bx_deal.c中,而bx_deal.c中的函数中用到的cJSON函数都在cJSON.c中,这样做的目的是,用bx_deal.c作为中间文件,能够在其中传参的时候,根据我们的需求以及实际使用,更具灵活性,像这里,几个函数:
SK_API int bx_deal_init(const char *p_fileName);
/// @brief 模块反初始化
SK_API int bx_deal_quit();
/// @brief 按下标读取一条信息
/// @param [in] seq: 序号
/// @param [out] p_dealInfo: 保存交易记录的结构体
/// @return 0:成功 非0:失败
/// 将结果存到一个结构体中,即*p_dealInfo;
SK_API int bx_read_dealInfo(unsigned short seq,deal_info_t *p_dealInfo);
/// @brief 按下标读取一条信息
/// @param [in] seq: 序号
/// @param [in] p_dealInfo: 交易记录的结构体
/// @return 0:成功 非0:失败
SK_API int bx_write_dealInfo(deal_info_t *p_dealInfo);
/// @brief 获取最新的交易记录下标
/// @return 最新的交易记录下标
SK_API unsigned short bx_get_max_index();
这几个函数方便我们处理自己传递的数据信息(这里主要是以将充电信息以结构体的信息输出),最后实现的就是将我们的充电信息(结构体,在文件中pub_type.h有定义),从传进来的结构体读入文件中,然后在需要显示的时候,从文件提取出来,或者读出来;
程序源码分析:
程序梳理:
这里主要是由:
cJSON的接口函数文件 - cJSON.c和cJSON.h;
主要包含充电信息结构体的头文件 - pub_type.h
主要包含充电信息结构体等的头文件baoxin_def.h:
test.c就是我们的头文件,里面写好了main函数,使用bx_deal.c中的一些用户函数,然后这些用户函数又套用了cJSON.c中的一些头文件;
所以我们在编译的时候需要:
注:会生成一个文本文件,chargeinfo.txt;
程序联系:
test.c中用了bx_deal.c中的函数,bx_deal.c中又套用了cJSON.c中的函数;
test.c中用到了baoxin_def.h中充电信息结构体,而这个结构体中用到了pub_type.h的SK_TIME结构体成员;
bx_deal.h和CJSON.h分别是bx_deal.c和CJSON.c里面是对他们的头文件中的函数的声明;
chargeinfo.txt是这个程序运行生成的;
程序分析:
下面给出除了cJSON.h和cJSON.c以外的头文件,这两个文件可以在网上找到,给出了bx_deal.c,bx_deal.h,test.c,pub_type.h,baoxin_def.h等五个文件,共七个文件;以及编译,运行程序生成的文本文件chargeinfo.txt;
bx_deal.c文件:
#include "baoxin_def.h"
#include "bx_deal.h"
#include
#include "cJSON.h"
#include
#include
#include
//const char *g_dealFile = "usr/data/deal.json";
//const char *g_dealFile = "/mnt/hgfs/share_for_linux/cJSON_lib_use/chargeinfo.txt";
const char START_TIME[] = "start_time";
const char STOP_TIME[] = "stop_time";
const char CHARGE_TIME[] = "charge_time";
const char TOTAL_KWH[] = "total_kwh";
const char SEQ[] = "seq";
typedef struct bx_dealInfo_t
{
char * p_text;
cJSON * p_deal;
int buf_len;
int max_num;
char path[128];
}bx_dealInfo_t;
const int MAX_BUF_SIZE = 16 * 1024;
const int MAX_DEAL_NUM = 100;
static bx_dealInfo_t *g_p_dealInfo = NULL;
static void event_write()
{
assert(NULL != g_p_dealInfo->p_text);
//
while (g_p_dealInfo->buf_len < strlen(g_p_dealInfo->p_text))
{
free(g_p_dealInfo->p_text);
g_p_dealInfo->p_text = NULL;
//删除最老的记录
int count = cJSON_GetArraySize(g_p_dealInfo->p_deal);
if (g_p_dealInfo->max_num < count)
cJSON_DeleteItemFromArray(g_p_dealInfo->p_deal, count - 1);
g_p_dealInfo->p_text = cJSON_PrintUnformatted(g_p_dealInfo->p_deal);
}
assert(NULL != g_p_dealInfo->p_text);
//刷新到文件
FILE *p_file = fopen(g_p_dealInfo->path, "w");
assert(NULL != p_file);
int len = fwrite(g_p_dealInfo->p_text, 1, strlen(g_p_dealInfo->p_text), p_file);
assert(len == strlen(g_p_dealInfo->p_text));
fclose(p_file);
}
int bx_dealInfo_init(const char *p_path)
{
assert(NULL != p_path);
assert(NULL == g_p_dealInfo);
g_p_dealInfo = malloc(sizeof(bx_dealInfo_t));
memset(g_p_dealInfo, 0, sizeof(bx_dealInfo_t));
g_p_dealInfo->buf_len = MAX_BUF_SIZE ;
g_p_dealInfo->max_num = MAX_DEAL_NUM ;
FILE *p_file = fopen(p_path, "r");
if (NULL == p_file)
{
g_p_dealInfo->p_text = NULL;
//若没有文件,则创建JSON句柄
g_p_dealInfo->p_deal = cJSON_CreateArray();
}
else
{
g_p_dealInfo->p_text = (char*)malloc(g_p_dealInfo->buf_len + 2048);
memset(g_p_dealInfo->p_text, 0, g_p_dealInfo->buf_len + 2048);
//读取文件内容初始化JSON句柄
int len = fread(g_p_dealInfo->p_text, 1, g_p_dealInfo->buf_len, p_file);
fclose(p_file);
assert(0 < len);
//解析一个对象,并将其返回值给p_deal
g_p_dealInfo->p_deal = cJSON_Parse(g_p_dealInfo->p_text);
assert(cJSON_Array == g_p_dealInfo->p_deal->type);
}
//g_p_dealInfo->p_mutex = sys_mutex_create();
//记录文件路径
strcpy(g_p_dealInfo->path, p_path);
return 0;
}
int bx_deal_quit()
{
assert(NULL != g_p_dealInfo);
assert(NULL != g_p_dealInfo->p_deal);
g_p_dealInfo->p_deal = NULL; //
if (NULL != g_p_dealInfo->p_text)
{
//刷新到文件
event_write();
free(g_p_dealInfo->p_text);
}
cJSON_Delete(g_p_dealInfo->p_deal);
free(g_p_dealInfo);
g_p_dealInfo = NULL;
return 0;
}
/// @brief 按下标读取一条信息
/// @param [in] seq: 序号
/// @param [out] p_dealInfo: 保存交易记录的结构体
/// @return 0:成功 非0:失败
// int bx_read_dealInfo(unsigned int seq, deal_info_t *p_dealInfo)
int bx_read_dealInfo(unsigned short seq,deal_info_t *p_dealInfo)
{
printf("+++++bx_read_dealInfo++++\n");
assert(NULL != g_p_dealInfo);
char *out = NULL;
cJSON *pArrayItem = NULL;
//获取数组的节点数量size
int count = cJSON_GetArraySize(g_p_dealInfo->p_deal);
pArrayItem = cJSON_GetArrayItem(g_p_dealInfo->p_deal, count-seq);
printf("***********seq = %d*********\n",seq);
//将pArrayItem的值以字串的形式打印到char型buffer上,cJSON_Print()会自动分配内存空间,用完需要释放内存。
out = cJSON_Print( pArrayItem );
printf("%s\n",out);
//指定格式: 2016/08/30 18:19:30
//start_time
printf("++++++++++++++++++++\n");
cJSON* start_time_temp = cJSON_GetObjectItem(pArrayItem, START_TIME);
sscanf(start_time_temp->valuestring, "%d/%d/%d %d:%d:%d\n", \
&(p_dealInfo->start_time.year),&(p_dealInfo->start_time.mon),&(p_dealInfo->start_time.mday), \
&(p_dealInfo->start_time.hour),&(p_dealInfo->start_time.min),&(p_dealInfo->start_time.sec));
printf("++++p_dealInfo->start_time.year = %d++++\n",p_dealInfo->start_time.year);
printf("++++p_dealInfo->start_time.mon = %d++++\n",p_dealInfo->start_time.mon);
printf("++++p_dealInfo->start_time.mday = %d++++\n",p_dealInfo->start_time.mday);
printf("++++p_dealInfo->start_time.hour = %d++++\n",p_dealInfo->start_time.hour);
printf("++++p_dealInfo->start_time.min = %d++++\n",p_dealInfo->start_time.min);
printf("++++p_dealInfo->start_time.sec = %d++++\n",p_dealInfo->start_time.sec);
printf("+++++++++++++++%s(%d)\n",__FILE__,__LINE__);
//指定格式: 2016/08/30 18:19:30
//stop_time
printf("++++++++++++++++++++\n");
cJSON* stop_time_temp = cJSON_GetObjectItem(pArrayItem, STOP_TIME);
sscanf(stop_time_temp->valuestring, "%d/%d/%d %d:%d:%d\n", \
&(p_dealInfo->stop_time.year),&(p_dealInfo->stop_time.mon),&(p_dealInfo->stop_time.mday), \
&(p_dealInfo->stop_time.hour),&(p_dealInfo->stop_time.min),&(p_dealInfo->stop_time.sec));
printf("++++p_dealInfo->stop_time.year = %d++++\n",p_dealInfo->stop_time.year);
printf("++++p_dealInfo->stop_time.mon = %d++++\n",p_dealInfo->stop_time.mon);
printf("++++p_dealInfo->stop_time.mday = %d++++\n",p_dealInfo->stop_time.mday);
printf("++++p_dealInfo->stop_time.hour = %d++++\n",p_dealInfo->stop_time.hour);
printf("++++p_dealInfo->stop_time.min = %d++++\n",p_dealInfo->stop_time.min);
printf("++++p_dealInfo->stop_time.sec = %d++++\n",p_dealInfo->stop_time.sec);
printf("+++++++++++++++%s(%d)\n",__FILE__,__LINE__);
printf("++++++++++++++++++++\n");
cJSON* charge_time_temp = cJSON_GetObjectItem(pArrayItem, CHARGE_TIME);
if(charge_time_temp->valueint == 0)
{
printf("++++++++++no_charge++++++++++\n");
return 0;
}else{
p_dealInfo->charge_time = charge_time_temp->valueint;
printf("++++p_dealInfo->charge_time = %d++++\n",p_dealInfo->charge_time);
}
printf("++++++++++++++++++++\n");
cJSON* total_kwh_temp = cJSON_GetObjectItem(pArrayItem, TOTAL_KWH);
p_dealInfo->total_kwh = total_kwh_temp->valueint;
printf("++++p_dealInfo->total_kwh = %d++++\n",p_dealInfo->total_kwh);
// 释放内存
cJSON_Delete(pArrayItem);
pArrayItem = NULL;
free(out);
out = NULL;
return 0;
}
/// @brief 获取最新的交易记录下标
/// @return 最新的交易记录下?
unsigned short bx_get_max_index()
{
#if 0
printf("+++++bx_get_max_no++++\n");
//获取数组的节点数量size
unsigned short count = cJSON_GetArraySize(g_p_dealInfo->p_deal);
printf("++++++++++count = %d+++++++++\n",count);
#endif
return 0;
}
int bx_write_dealInfo(deal_info_t *p_dealInfo)
{
assert(NULL != g_p_dealInfo);
//assert(NULL !=p_dealInfo);
printf("+++++bx_write_dealInfo++++\n");
cJSON* p_data = cJSON_CreateObject();
//向数组array中插入新的项目
cJSON_InsertItemInArray(g_p_dealInfo->p_deal, 0, p_data);
//获取数组的节点数量size
int count = cJSON_GetArraySize(g_p_dealInfo->p_deal);
//删除最早的记录
if (g_p_dealInfo->max_num < count)
cJSON_DeleteItemFromArray(g_p_dealInfo->p_deal, count - 1);
//输出该结构体的信息到p_data内
char str_time[32] = { 0 };
sprintf(str_time, "%4d/%02d/%02d %02d:%02d:%02d", p_dealInfo->start_time.year,p_dealInfo->start_time.mon, p_dealInfo->start_time.mday, p_dealInfo->start_time.hour,p_dealInfo->start_time.min,p_dealInfo->start_time.sec);
cJSON_AddStringToObject(p_data, START_TIME, str_time);
memset(str_time,0,32);
sprintf(str_time, "%4d/%02d/%02d %02d:%02d:%02d", p_dealInfo->stop_time.year, p_dealInfo->stop_time.mon, p_dealInfo->stop_time.mday, p_dealInfo->stop_time.hour,p_dealInfo->stop_time.min, p_dealInfo->stop_time.sec);
cJSON_AddStringToObject(p_data, STOP_TIME, str_time);
cJSON_AddNumberToObject(p_data, CHARGE_TIME, p_dealInfo->charge_time);
cJSON_AddNumberToObject(p_data, TOTAL_KWH, p_dealInfo->total_kwh);
#if 0
if (NULL != p_dealInfo->p_text)
{
free(p_dealInfo->p_text);
p_dealInfo->p_text = NULL;
}
#endif
if (NULL != g_p_dealInfo->p_text)
{
free(g_p_dealInfo->p_text);
g_p_dealInfo->p_text = NULL;
}
//刷新到文件2016.8.25
//p_dealInfo->p_text = cJSON_PrintUnformatted(p_dealInfo->p_event);
g_p_dealInfo->p_text = cJSON_Print(g_p_dealInfo->p_deal);
event_write();
}
test.c文件:
#include
#include "cJSON.h"
#include "baoxin_def.h"
#include "bx_deal.h"
//struct deal_info_t *p_dealInfo = NULL;
struct deal_info_t p_dealInfo;
struct deal_info_t p_dealInfo1 =
{
{2016,8,21,7,15,10,30,0}, //2016/8/25 14:58:30"
{2016,8,21,7,16,10,30,0}, //"2016/8/25 15:58:30"
1,
7
};
struct deal_info_t p_dealInfo2 =
{
{2016,8,22,7,15,10,30,0}, //2016/8/25 14:58:30"
{2016,8,22,7,16,10,30,0}, //"2016/8/25 15:58:30"
1,
7
};
struct deal_info_t p_dealInfo3 =
{
{2016,8,23,7,15,10,30,0}, //2016/8/25 14:58:30"
{2016,8,23,7,16,10,30,0}, //"2016/8/25 15:58:30"
1,
7
};
struct deal_info_t p_dealInfo4 =
{
{2016,8,24,7,15,10,30,0}, //2016/8/25 14:58:30"
{2016,8,24,7,16,10,30,0}, //"2016/8/25 15:58:30"
1,
7
};
struct deal_info_t p_dealInfo5 =
{
{2016,8,25,7,15,10,30,0}, //2016/8/25 14:58:30"
{2016,8,25,7,16,10,30,0}, //"2016/8/25 15:58:30"
1,
7
};
struct deal_info_t p_dealInfo6 =
{
{2016,8,26,7,15,10,30,0}, //2016/8/25 14:58:30"
{2016,8,26,7,16,10,30,0}, //"2016/8/25 15:58:30"
1,
7
};
const char *p_path = "chargeinfo.txt";
//const char *p_path = "/mnt/hgfs/share_for_linux/cJSON_lib_use/chargeinfo.txt";
int main()
{
bx_dealInfo_init(p_path);
#if 0
bx_write_dealInfo(&p_dealInfo1);
bx_write_dealInfo(&p_dealInfo2);
bx_write_dealInfo(&p_dealInfo3);
bx_write_dealInfo(&p_dealInfo4);
bx_write_dealInfo(&p_dealInfo5);
bx_write_dealInfo(&p_dealInfo6);
#endif
bx_get_max_index();
//bx_read_dealInfo(1,&p_dealInfo);
bx_read_dealInfo(2,&p_dealInfo);
//bx_read_dealInfo(3,&p_dealInfo);
//bx_read_dealInfo(4,&p_dealInfo);
//bx_read_dealInfo(5,&p_dealInfo);
//bx_read_dealInfo(6,&p_dealInfo);
bx_deal_quit();
//system_pause();
return 0;
pub_type.h文件:
#ifndef __PUB_TYPE_H__
#define __PUB_TYPE_H__
#include
#ifdef __cplusplus
#define SK_API extern "C"
#else
#define SK_API extern
#endif
#pragma pack(push) //
#pragma pack(4)
/// @name _SK_TIME_
/// @brief 时间描述
#if 0
typedef struct SK_TIME
{
unsigned short year; ///< 某年
unsigned char mon; ///< 某月
unsigned char mday; ///< 某日
unsigned char wday; ///< 星期几
unsigned char hour; ///< 时
unsigned char min; ///< 分
unsigned char sec; ///< 秒
int msec; ///< 豪秒
}SK_TIME;
#endif
typedef struct SK_TIME
{
unsigned short year; ///< 某年
unsigned char mon; ///< 某月
unsigned char mday; ///< 某日
unsigned char wday; ///< 星期几
unsigned char hour; ///< 时
unsigned char min; ///< 分
unsigned char sec; ///< 秒
int msec; ///< 豪秒
}SK_TIME;
#pragma pack(pop)//
#endif // __PUB_TYPE_H__
//end
baoxin_def.h:
///////////////////////////////////////////////////////////////////////////
//
/// @file baoxin.h
/// @brief 与宝信车联网的通信模块
/// @author
/// @version 0.1
/// @history 修改历史
/// @warning 没有警告
///////////////////////////////////////////////////////////////////////////
#ifndef __BAO_XIN_DEF_H__
#define __BAO_XIN_DEF_H__
#include
#include"pub_type.h"
#define BX_LOGIN_CODE_LEN 32 //登录码的最大长度
#define BX_MSG_HEADER_LEN 12 //消息头的最大长度
#define BX_CELL_PHONE_LEN 12 //终端手机号码的最大长度
#define BX_MSG_CRC_LEN 1 //校验码长度
#pragma pack(push) //
#pragma pack(1)
typedef struct bx_ser_info_t
{
unsigned char server[4]; //4个字节,从高位到低位,依次对应IP地址的4个段
unsigned short port; //端口号
}bx_ser_info_t;
typedef struct cp_state_t
{
unsigned char elec_lock_state ;
//电磁锁的状态 0:关闭状态 1:打开状态 2:无电磁锁
//充电枪的状态 0:充电枪处于与桩连接状态;(暂时无)1:充电枪处于与车连接状态;2:充电枪处于悬空状态;3:充电枪与车连接并且车已经准备好
unsigned char cp_error;
//充电桩故障 0:无故障 1:有故障
//总电量3字节,高8位、中间8位、低8位。总电量,单位为W.H
unsigned char current;
//充电电流值单位为安培(A)
}cp_state_t;
typedef struct login_info_t
{
unsigned char login_code[32] ; //登录码
}login_info_t;
typedef struct result_reply_t
{
unsigned char answer ; //充电状态设置结果:0设置成功,1设置失败
}result_reply_t;
typedef struct deal_info_t
{
//unsigned short seq ; //查询的交易记录号
SK_TIME start_time; //充电的开始时间
SK_TIME stop_time; //充电的结束时间
unsigned int charge_time; //充电时长
unsigned int total_kwh; //充电总电度
}deal_info_t;
#pragma pack(pop)//
bx_deal.h文件:
#ifndef __BX_DEAL_H__
#define __BX_DEAL_H__
#include "pub_type.h"
/// @brief 模块初始化
/// @param [in] p_fileName: 文件路径
/// @return 0:成功 非0:失败
SK_API int bx_deal_init(const char *p_fileName);
/// @brief 模块反初始化
SK_API int bx_deal_quit();
/// @brief 按下标读取一条信息
/// @param [in] seq: 序号
/// @param [out] p_dealInfo: 保存交易记录的结构体
/// @return 0:成功 非0:失败
/// 将结果存到一个结构体中,即*p_dealInfo;
SK_API int bx_read_dealInfo(unsigned short seq,deal_info_t *p_dealInfo);
/// @brief 按下标读取一条信息
/// @param [in] seq: 序号
/// @param [in] p_dealInfo: 交易记录的结构体
/// @return 0:成功 非0:失败
SK_API int bx_write_dealInfo(deal_info_t *p_dealInfo);
/// @brief 获取最新的交易记录下标
/// @return 最新的交易记录下标
SK_API unsigned short bx_get_max_index();
#endif
小结论:在这个小工程中,运用了cJSON的接口函数,方便让我从人为定义的结构体,这里是包含了充电的信息,将这些信息(结构体)通过cJSON接口函数,以cJSON结构存入指定文件中chargeinfo.txt,并从这个文件以cJSON函数方便的读取出里面的相应序号的充电信息,并以指定的充电信息的结构体形式输出;非常方便;