当前位置: 首页 > news >正文

C语言,用json文件存储tree

C语言,用json文件存储tree:

1.读取和保存都用递归算法遍历,可以保存任意树结构,相比用INI文件,一致性更好,当然用数据库功能更多更好
2.json数据全部用节点最方便,缺点存储的json文件末端有一个空的{},不太美观
3.json文件读入时最好判断编码,尤其是对手工编辑的文件
4.json的root节点没必要创建在树上,除非要展现多个json文件在同一树上


5.测试程序用VS2010的MFC模板,加入CJSON文件,主要程序段如下:

 

//保存树到json中

cJSON * CFileView::AddJsonNode(HTREEITEM hItem, cJSON *NodePrev)
{char text[256];CString str = m_wndFileView.GetItemText(hItem);HWND hWndTree = m_wndFileView.m_hWnd;HTREEITEM hChild = TreeView_GetChild(hWndTree, hItem);char *p = WcharToChar(str.GetBuffer(0), CP_UTF8);cJSON *node;//if(hChild != NULL)
    {node = cJSON_CreateObject();cJSON_AddItemToObject(NodePrev, p, node);delete p;return node;}/*else //没必要,反正要有个多余的,用{}也可以,所以都用Obj{cJSON_AddStringToObject(NodePrev, p, " ");delete p;return NodePrev;}*/PRINT(_T("\r\n %s"), str.GetBuffer(0));
}void CFileView::RecursionTreeSave(HTREEITEM hItem, cJSON *NodePrev)
{if (!hItem)    return;HWND hWndTree = m_wndFileView.m_hWnd;cJSON *node = AddJsonNode(hItem, NodePrev); //递归函数中增加节点必须在子节点前
    HTREEITEM hChild = TreeView_GetChild(hWndTree, hItem);RecursionTreeSave(hChild, node);  //进入子节点
       HTREEITEM hSibling =  TreeView_GetNextSibling(hWndTree, hItem);   RecursionTreeSave(hSibling, NodePrev);//DeleteNode(hItem);  //递归函数中删除只能处理当前节点,放在子节点处理后再处理当前节点 return;
}

//======
。。。。。。。
//下面是把树保存为json文件
    HTREEITEM hRoot = m_wndFileView.GetRootItem();CFileJson fjson(NULL);if(fjson.root != 0) cJSON_Delete(fjson.root);fjson.root = 0;// 创建 JSON rootfjson.root = cJSON_CreateObject();RecursionTreeSave(hRoot, fjson.root);fjson.Save("r:\\tree.json");

 

//======================
//从json读取数据生成树
HTREEITEM CFileView::AddTreeNode(cJSON *jNode, HTREEITEM hParen, HTREEITEM hAfter) {cJSON * node = jNode;if(node == NULL) return NULL;wchar_t *p = CharToWchar(node->string, CP_UTF8);HTREEITEM hItem;if(node->child){hItem = m_wndFileView.InsertItem(p, 0, 0, hParen, hAfter);delete p;}else{hItem = m_wndFileView.InsertItem(p, 1, 1, hParen, hAfter);delete p;} return hItem; }void CFileView::RecursionTreeLoad(cJSON *jNode, HTREEITEM hParen, HTREEITEM hAfter) {cJSON * node = jNode;if(node == NULL) return;HWND hWndTree = m_wndFileView.m_hWnd;HTREEITEM hItem = AddTreeNode(jNode, hParen, hAfter); //递归函数中增加节点必须在子节点前 cJSON* jNodeChild = node->child;RecursionTreeLoad(jNodeChild, hItem, NULL); //进入child节点 cJSON* jNodeNext = node->next;RecursionTreeLoad(jNodeNext, hParen, hItem); //进入Next节点return; }

//===================

// 下面是从json文件读取数据,用来生成树,root节点不显示,从root的子节点开始

。。。。。
CFileJson fjson("r:\\tree1.json");if(fjson.root == 0){PRINT(_T("\r\n Open fail!"));return;}m_wndFileView.DeleteAllItems();cJSON *node = fjson.root->child; //XGZ:ROOT NOT FOR TREE NODE RecursionTreeLoad(node, NULL, NULL);HTREEITEM hRoot = m_wndFileView.GetRootItem();m_wndFileView.Expand(hRoot, TVE_EXPAND);

//===Json的c++封装,只是为了可靠释放

class CFileJson 
{
public:CFileJson(const char* filepathname);~CFileJson();cJSON * root;
int Save(const char* filepathname);

};

//另外要注意文件打开时判断编码,保存时默认字符串生成UTF-8,

//若只是自己的程序存取自己的文件,这些判断转换都不用,只要打开文件直接读取就行了

CFileJson::CFileJson(const char* filepathname)
{root = 0;if(filepathname == NULL) return;wchar_t* pwText;int length;FILE* fp = fopen(filepathname, "rb");if (fp){fseek(fp, 0, SEEK_END);  //到文件末尾,0 succesint FileLen = ftell(fp);  //到末尾后的位置就是文件长度char* p1;wchar_t* p2;p1 = new char[FileLen + 16];fseek(fp, 0, SEEK_SET);  //回到0位置, 0 succeslength = fread(p1, 1, FileLen + 16, fp);fclose(fp);*(p1 + length) = 0;*(p1 + length + 1) = 0;*(p1 + length + 2) = 0;*(p1 + length + 3) = 0;if (((unsigned char)*p1 == 0xff)&& ((unsigned char)*(p1 + 1) == 0xfe))  //UTF-16LE
        {for (int i = 0; i < length; i += 2){*(p1 + i) = *(p1 + i + 2);*(p1 + i + 1) = *(p1 + i + 3);}pwText = (wchar_t*)(p1);}else if (((unsigned char)*p1 == 0xfe)&& ((unsigned char)*(p1 + 1) == 0xff))  //UTF-16BE
        {for (int i = 0; i < length; i += 2){*(p1 + i) = *(p1 + i + 3);*(p1 + i + 1) = *(p1 + i + 2);} pwText = (wchar_t*)(p1);}else if (((unsigned char)*p1 == 0xef)&& ((unsigned char)*(p1 + 1) == 0xbb)&& ((unsigned char)*(p1 + 2) == 0xbf))//UTF-8 BOM
        {p2 = CharToWchar(p1 + 3, CP_UTF8);delete p1;pwText = (wchar_t*)p2;}else  //ANSI, UTF-8
        {int checknum = FileLen;  //1000000;  //XGZ:NEED CHECK if (checknum > length) checknum = length;if (IsUTF8Text(p1, checknum))  //UTF-8
            {root = cJSON_Parse(p1);delete p1;return; //XGZ: THIS APP, CP_UTF8 NO NEED CHANGE TO UTF16LE//p2 = CharToWchar(p1, CP_UTF8);//delete p1;//pwText = (wchar_t*)p2;
            }else  //ASCII CP_ACP
            {p2 = CharToWchar(p1, CP_ACP);delete p1;pwText = (wchar_t*)p2;}}char * pdata = WcharToChar(pwText, CP_UTF8);root = cJSON_Parse(pdata);  //XGZ:DEFAULT CODE CP_UTF8delete pdata;}return;
}
CFileJson::~CFileJson()
{if(root != 0){cJSON_Delete(root);root = 0;}return;
}int CFileJson::Save(const char* filepathname)
{FILE *fp = fopen(filepathname,"wb");if(root != 0){char *pdata = cJSON_Print(root); //XGZ:DEFAULT CODE CP_UTF8if(pdata != NULL){fwrite(pdata,sizeof(char), strlen(pdata), fp);}free(pdata);  //cJSON use malloc  //static void *(*cJSON_malloc)(size_t sz) = malloc;
    }fclose(fp);return 0;
}

 

 

 

程序读取json文件后显示在tree上

image

 

json文件: 

image

 

http://www.jsqmd.com/news/65349/

相关文章:

  • 数通核心专业书
  • 10 数据库表的关联
  • 【C++】哈希表:简单易懂的核心讲解(含实战用法)
  • PFLS
  • Dify 自建部署完全指南:从上手到放弃到真香
  • 工业设计必备工具:3ds Max 2025 三维建模 影视特效 下载安装教程
  • 组合计数题没做
  • 城市内涝监测架构-恒星物联解决方案
  • 院长码上办-患者投诉接办管理系统
  • 2025上海黛丽汀立体停车设备厂家实力榜:智能垂直升降技术领跑,六家高潜力本土品牌深度解析
  • 代数数论与模块格基础学习
  • 【Azure App Service】部署在应用服务上的WebJob中,为何会多出一个名为DaaS的 WebJob呢?
  • 2025上海立体车库厂家实力榜:黛丽汀以智能垂直循环技术领跑,六家高潜力本土品牌深度解析
  • spec kit 探索性问答
  • R语言保存file路径问题
  • 2025最新深圳/惠州输送线厂家TOP5推荐!深圳惠州地区组装线/装配线/生产线/输送线/老化线选购优质供应商评测
  • 【Java】面向对象基础
  • 退役入生前最后一道题
  • 归并分治模板
  • 2025燕窝品牌实力排行榜:艾玛琳商贸以溯源科技领衔,六大高潜力燕窝衍生品与礼品企业深度解析
  • ABC 435 解题报告
  • 【创作分享】一个简单易用、功能强大的 AI 图片生成工具:NanoEdit(基于Gemini 3.0 Nano Banana Pro)
  • 街头徒手健身4高阶引体向上
  • shell脚本内使用alias
  • 告别手动编码:如何用Screenshot-to-code搭建设计稿自动转HTML全流程
  • Helloworld
  • 实验4
  • ffmpeg移植到arm
  • 英语_阅读_songs playlists_待读
  • Hello,World!