CJSON由于简洁明了的格式特征,非常适合用于配置文件格式,下面以一个简单的配置文件为例讲解cjson格式文件读写方法。
cjson格式文件recordcfg.txt示例:
{
"record_cfg": {
"record_chan": [1, 1],
"live_chan": [1, 1],
"fps": 30,
"bitrate": 12
}
}
cjson配置文件读写代码:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <pthread.h>
#include <errno.h>
#include <signal.h>
#include <sys/mman.h>
#include "cJSON.h"
#define RECORD_CFG_MAX 512
typedef struct RECORD_CONF{
int record_chan0;
int record_chan1;
int live_chan0;
int live_chan1;
int fps;
int bitrate;
}RECORD_CONF_t;
static void RecordConfDataParse(RECORD_CONF_t *pCfg, const char *jsonRecordData);
static int read_cfg_file(char *fileName, char *data);
static int write_cfg_file(char *fileName, char *data);
static int read_cfg_file(char *fileName, char *data)
{
long int file_len = 0;
FILE *fp = NULL;
if(!data || !fileName)
{
return -1;
}
if ((fp = fopen(fileName, "r")) == NULL)
{
printf("Open file error!\n");
//exit(EXIT_FAILURE);
return -1;
}
fseek(fp, 0, SEEK_END);
file_len = ftell(fp);
if(RECORD_CFG_MAX < file_len)
{
printf("record config file len error\n");
return -1;
}
fseek(fp, 0, SEEK_SET);
fread(data,(long unsigned int)file_len,1,fp);
fclose(fp);
return 0;
}
static int write_cfg_file(char *fileName, char *data)
{
long int file_len = 0;
FILE *fp = NULL;
long unsigned int data_len = 0;
if(!data || !fileName)
{
return -1;
}
data_len = strlen(data);
if ((fp = fopen(fileName, "w+")) == NULL)
{
printf("Open file error!\n");
//exit(EXIT_FAILURE);
return -1;
}
fseek(fp, 0, SEEK_SET);
fwrite(data, data_len, 1, fp);
fclose(fp);
return 0;
}
void ReadRecordConf(char *fileName, RECORD_CONF_t *pCfg)
{
cJSON *record_json = NULL;
cJSON *record_chan = NULL;
cJSON *live_chan = NULL;
cJSON *fps = NULL;
cJSON *bitrate = NULL;
cJSON *root = NULL;
char *data = NULL;
cJSON *arrayItem = NULL;
int i = 0;
data = (char *)malloc((long unsigned int)RECORD_CFG_MAX);
if(read_cfg_file(fileName, data))
{
goto end;
}
root = cJSON_Parse((const char *)data);
if (NULL == root)
{
const char *error_ptr = cJSON_GetErrorPtr();
if (error_ptr != NULL)
{
fprintf(stderr, "Error before: %s\n", error_ptr);
}
goto end;
}
record_json = cJSON_GetObjectItemCaseSensitive(root, "record_cfg");
if (NULL == record_json)
{
const char *error_ptr = cJSON_GetErrorPtr();
if (error_ptr != NULL)
{
fprintf(stderr, "Error before: %s\n", error_ptr);
}
goto end;
}
arrayItem = cJSON_GetObjectItem(record_json,"record_chan");
for(i=0;i<RECORD_VIDEO_CHAN_MAX;i++)
{
record_chan = cJSON_GetArrayItem(arrayItem, i);
if (cJSON_IsNumber(record_chan))
{
pCfg->record_chan[i] = record_chan->valueint;
}
}
arrayItem = cJSON_GetObjectItem(record_json,"live_chan");
for(i=0;i<RECORD_VIDEO_CHAN_MAX;i++)
{
live_chan = cJSON_GetArrayItem(arrayItem, 0);
if (cJSON_IsNumber(live_chan))
{
pCfg->live_chan[i] = live_chan->valueint;
}
}
fps = cJSON_GetObjectItemCaseSensitive(record_json, "fps");
if (cJSON_IsNumber(fps))
{
pCfg->fps = fps->valueint;
}
bitrate = cJSON_GetObjectItemCaseSensitive(record_json, "bitrate");
if (cJSON_IsNumber(bitrate))
{
pCfg->bitrate = bitrate->valueint;
}
end:
free(data);
data = NULL;
cJSON_Delete(root);
}
void WriteRecordConf(char *fileName, RECORD_CONF_t *pCfg)
{
cJSON *record_json = NULL;
cJSON *record_chan = NULL;
cJSON *live_chan = NULL;
cJSON *fps = NULL;
cJSON *bitrate = NULL;
cJSON *root = NULL;
char *out = NULL;
char *data = NULL;
int i = 0;
cJSON *arrayItem = NULL;
data = (char *)malloc((long unsigned int)RECORD_CFG_MAX);
if(read_cfg_file(fileName, data))
{
goto end;
}
root = cJSON_Parse((const char *)data);
if (NULL == root)
{
const char *error_ptr = cJSON_GetErrorPtr();
if (error_ptr != NULL)
{
fprintf(stderr, "Error before: %s\n", error_ptr);
}
goto end;
}
record_json = cJSON_GetObjectItemCaseSensitive(root, "record_cfg");
if (NULL == record_json)
{
const char *error_ptr = cJSON_GetErrorPtr();
if (error_ptr != NULL)
{
fprintf(stderr, "Error before: %s\n", error_ptr);
}
goto end;
}
arrayItem = cJSON_GetObjectItem(record_json,"record_chan");
for(i=0;i<RECORD_VIDEO_CHAN_MAX;i++)
{
cJSON_ReplaceItemInArray(arrayItem, i, cJSON_CreateNumber(pCfg->record_chan[i]));
}
arrayItem = cJSON_GetObjectItem(record_json,"live_chan");
for(i=0;i<RECORD_VIDEO_CHAN_MAX;i++)
{
cJSON_ReplaceItemInArray(arrayItem, i, cJSON_CreateNumber(pCfg->live_chan[i]));
}
cJSON_ReplaceItemInObjectCaseSensitive(record_json,"fps",cJSON_CreateNumber(pCfg->fps));
cJSON_ReplaceItemInObjectCaseSensitive(record_json,"bitrate",cJSON_CreateNumber(pCfg->bitrate));
out = cJSON_Print(root);
printf("out:\n%s\n",out);
write_cfg_file(fileName, out);
end:
free(data);
data = NULL;
cJSON_Delete(root);
}
void PrintParseResult(const RECORD_CONF_t *pCfg)
{
int i = 0;
for(i=0;i<2;i++)
{
printf("record_chan[%d]: %d, live_chan[%d]: %d\n",i, pCfg->record_chan[i], i,
pCfg->live_chan[i]);
}
printf("fps: %d, bitrate: %d\n", pCfg->fps, pCfg->bitrate);
}
int main(void)
{
RECORD_CONF_t cfg = {0};
ReadRecordConf("recordcfg.txt",&cfg);
PrintParseResult(&cfg);
cfg.record_chan0 = 1;
cfg.record_chan1 = 1;
cfg.live_chan0 = 1;
cfg.live_chan1 = 1;
cfg.fps = 30;
cfg.bitrate = 12;
WriteRecordConf("recordcfg.txt", &cfg);
return 0;
}
cjson C库下载地址:
https://download.csdn.net/download/luky_zhou123/20057056
makefile修改:
增加以下行,本人是移植到海思,所以用的aarch64-himix100-linux-gcc,如果需要移植到其他平台修改成对应交叉编译环境
CROSS_COMPILE=aarch64-himix100-linux-
CC=$(CROSS_COMPILE)gcc
CXX=$(CROSS_COMPILE)g++
AR=$(CROSS_COMPILE)ar
RANLIB= $(CROSS_COOMPILE)ranlib
STRIP=$(CROSS_COMPILE)strip
CJSON_OBJ = cJSON.o
UTILS_OBJ = cJSON_Utils.o
CJSON_LIBNAME = libcjson
UTILS_LIBNAME = libcjson_utils
CJSON_TEST = cJSON_test
CJSON_TEST_SRC = cJSON.c test.c
LDLIBS = -lm
LIBVERSION = 1.7.14
CJSON_SOVERSION = 1
UTILS_SOVERSION = 1
CJSON_SO_LDFLAG=-Wl,-soname=$(CJSON_LIBNAME).so.$(CJSON_SOVERSION)
UTILS_SO_LDFLAG=-Wl,-soname=$(UTILS_LIBNAME).so.$(UTILS_SOVERSION)
PREFIX ?= /usr/local
INCLUDE_PATH ?= include/cjson
LIBRARY_PATH ?= lib
INSTALL_INCLUDE_PATH = $(DESTDIR)$(PREFIX)/$(INCLUDE_PATH)
INSTALL_LIBRARY_PATH = $(DESTDIR)$(PREFIX)/$(LIBRARY_PATH)
INSTALL ?= cp -a
#CC = gcc -std=c99 //注释掉之前定义的CC
#CC = gcc
# validate gcc version for use fstack-protector-strong
#MIN_GCC_VERSION = "4.9"
#GCC_VERSION := "`$(CC) -dumpversion`"
#IS_GCC_ABOVE_MIN_VERSION := $(shell expr "$(GCC_VERSION)" ">=" "$(MIN_GCC_VERSION)")
#ifeq "$(IS_GCC_ABOVE_MIN_VERSION)" "1"
# CFLAGS += -fstack-protector-strong
#else
# CFLAGS += -fstack-protector
#endif
PIC_FLAGS = -fPIC
#R_CFLAGS = $(PIC_FLAGS) -pedantic -Wall -Werror -Wstrict-prototypes -Wwrite-strings -Wshadow -Winit-self -Wcast-align -Wformat=2 -Wmissing-prototypes -Wstrict-overflow=2 -Wcast-qual -Wc++-compat -Wundef -Wswitch-default -Wconversion $(CFLAGS)
R_CFLAGS = $(PIC_FLAGS)
uname := $(shell sh -c 'uname -s 2>/dev/null || echo false')
#library file extensions
SHARED = so
STATIC = a
## create dynamic (shared) library on Darwin (base OS for MacOSX and IOS)
ifeq (Darwin, $(uname))
SHARED = dylib
CJSON_SO_LDFLAG = ""
UTILS_SO_LDFLAG = ""
endif
#cJSON library names
CJSON_SHARED = $(CJSON_LIBNAME).$(SHARED)
CJSON_SHARED_VERSION = $(CJSON_LIBNAME).$(SHARED).$(LIBVERSION)
CJSON_SHARED_SO = $(CJSON_LIBNAME).$(SHARED).$(CJSON_SOVERSION)
CJSON_STATIC = $(CJSON_LIBNAME).$(STATIC)
#cJSON_Utils library names
UTILS_SHARED = $(UTILS_LIBNAME).$(SHARED)
UTILS_SHARED_VERSION = $(UTILS_LIBNAME).$(SHARED).$(LIBVERSION)
UTILS_SHARED_SO = $(UTILS_LIBNAME).$(SHARED).$(UTILS_SOVERSION)
UTILS_STATIC = $(UTILS_LIBNAME).$(STATIC)
SHARED_CMD = $(CC) -shared -o
.PHONY: all shared static tests clean install
all: shared static tests
shared: $(CJSON_SHARED) $(UTILS_SHARED)
static: $(CJSON_STATIC) $(UTILS_STATIC)
tests: $(CJSON_TEST)
test: tests
./$(CJSON_TEST)
.c.o:
$(CC) -c $(R_CFLAGS) $<
#tests
#cJSON
$(CJSON_TEST): $(CJSON_TEST_SRC) cJSON.h
$(CC) $(R_CFLAGS) $(CJSON_TEST_SRC) -o $@ $(LDLIBS) -I.
#static libraries
#cJSON
$(CJSON_STATIC): $(CJSON_OBJ)
$(AR) rcs $@ $<
cp -f $(CJSON_STATIC) ../../out/linux/multi-core/lib/
#cJSON_Utils
$(UTILS_STATIC): $(UTILS_OBJ)
$(AR) rcs $@ $<
#shared libraries .so.1.0.0
#cJSON
$(CJSON_SHARED_VERSION): $(CJSON_OBJ)
$(CC) -shared -o $@ $< $(CJSON_SO_LDFLAG) $(LDFLAGS)
#cJSON_Utils
$(UTILS_SHARED_VERSION): $(UTILS_OBJ)
$(CC) -shared -o $@ $< $(CJSON_OBJ) $(UTILS_SO_LDFLAG) $(LDFLAGS)
#objects
#cJSON
$(CJSON_OBJ): cJSON.c cJSON.h
#cJSON_Utils
$(UTILS_OBJ): cJSON_Utils.c cJSON_Utils.h cJSON.h
#links .so -> .so.1 -> .so.1.0.0
#cJSON
$(CJSON_SHARED_SO): $(CJSON_SHARED_VERSION)
ln -s $(CJSON_SHARED_VERSION) $(CJSON_SHARED_SO)
$(CJSON_SHARED): $(CJSON_SHARED_SO)
ln -s $(CJSON_SHARED_SO) $(CJSON_SHARED)
#cJSON_Utils
$(UTILS_SHARED_SO): $(UTILS_SHARED_VERSION)
ln -s $(UTILS_SHARED_VERSION) $(UTILS_SHARED_SO)
$(UTILS_SHARED): $(UTILS_SHARED_SO)
ln -s $(UTILS_SHARED_SO) $(UTILS_SHARED)
#install
#cJSON
install-cjson:
mkdir -p $(INSTALL_LIBRARY_PATH) $(INSTALL_INCLUDE_PATH)
$(INSTALL) cJSON.h $(INSTALL_INCLUDE_PATH)
$(INSTALL) $(CJSON_SHARED) $(CJSON_SHARED_SO) $(CJSON_SHARED_VERSION) $(INSTALL_LIBRARY_PATH)
#cJSON_Utils
install-utils: install-cjson
$(INSTALL) cJSON_Utils.h $(INSTALL_INCLUDE_PATH)
$(INSTALL) $(UTILS_SHARED) $(UTILS_SHARED_SO) $(UTILS_SHARED_VERSION) $(INSTALL_LIBRARY_PATH)
install: install-cjson install-utils
#uninstall
#cJSON
uninstall-cjson: uninstall-utils
$(RM) $(INSTALL_LIBRARY_PATH)/$(CJSON_SHARED)
$(RM) $(INSTALL_LIBRARY_PATH)/$(CJSON_SHARED_VERSION)
$(RM) $(INSTALL_LIBRARY_PATH)/$(CJSON_SHARED_SO)
$(RM) $(INSTALL_INCLUDE_PATH)/cJSON.h
#cJSON_Utils
uninstall-utils:
$(RM) $(INSTALL_LIBRARY_PATH)/$(UTILS_SHARED)
$(RM) $(INSTALL_LIBRARY_PATH)/$(UTILS_SHARED_VERSION)
$(RM) $(INSTALL_LIBRARY_PATH)/$(UTILS_SHARED_SO)
$(RM) $(INSTALL_INCLUDE_PATH)/cJSON_Utils.h
remove-dir:
$(if $(wildcard $(INSTALL_LIBRARY_PATH)/*.*),,rmdir $(INSTALL_LIBRARY_PATH))
$(if $(wildcard $(INSTALL_INCLUDE_PATH)/*.*),,rmdir $(INSTALL_INCLUDE_PATH))
uninstall: uninstall-utils uninstall-cjson remove-dir
clean:
$(RM) $(CJSON_OBJ) $(UTILS_OBJ) #delete object files
$(RM) $(CJSON_SHARED) $(CJSON_SHARED_VERSION) $(CJSON_SHARED_SO) $(CJSON_STATIC) #delete cJSON
$(RM) $(UTILS_SHARED) $(UTILS_SHARED_VERSION) $(UTILS_SHARED_SO) $(UTILS_STATIC) #delete cJSON_Utils
$(RM) $(CJSON_TEST) #delete test