上一个博客讲了怎么用rapidjson读取中文字符串,但是有一个很明显的缺陷 就是不能直接读取数据编辑器导出的数据。下面我们来修复这个bug并且将代码精简到不到原来的一半大小。
上一博客的地址是:【cocos2dx】rapidjson使用方法以及中文显示的解决方法
不多说 直接上源码吧:
首先,数据编辑器导出的格式是:
[{"id":1,"content":"再次按下返回键退出游戏"},{"id":2,"content":"五子棋"},{"id":3,"content":"黑色方"},{"id":4,"content":"白色方"},{"id":5,"content":"当前玩家"},{"id":6,"content":"小提示:"},{"id":7,"content":"null"},{"id":8,"content":"null"},{"id":9,"content":"null"},{"id":10,"content":"null"},{"id":11,"content":"null"},{"id":12,"content":"null"},{"id":13,"content":"null"},{"id":14,"content":"null"},{"id":15,"content":"null"},{"id":16,"content":"null"},{"id":17,"content":"null"}]
导出的时候请选择以属性的方式导出
解析的类:
#pragma once
/*
* 获取字符串类 单例
* 用于获取JSON文件中的中文字符串
*/
#include "cocos2d.h"
#include <string>
#include <cocos-ext.h>
#include "cocostudioCocoStudio.h"
#include "uiCocosGUI.h"
USING_NS_CC;
USING_NS_CC_EXT;
using namespace std;
using namespace cocostudio;
/**
* 数据ID的宏定义,用于找到中文数据
*/
static int s_iExit = 1; //再次按下返回键退出游戏
class ReadString
{
protected:
rapidjson::Document m_doc; //暂存的数据
static ReadString* rs;
public:
static ReadString* getInstance();
std::string parse(int key);
private:
static ReadString* creat(std::string fileName);
bool init(std::string fileName);
ReadString(){};
~ReadString(void){};
};
然后是cpp:
#include "ReadString.h"
ReadString* ReadString::rs = nullptr; //初始化
ReadString* ReadString::creat(std::string fileName)
{
ReadString *RS = new ReadString();
if(!RS || !RS->init(fileName))
{
delete RS;
RS = nullptr;
return nullptr;
}
return RS;
}
bool ReadString::init(std::string fileName)
{
bool ret = false;
do {
std::string jsonpath = FileUtils::getInstance()->fullPathForFilename(fileName);
std::string contentStr = FileUtils::getInstance()->getStringFromFile(jsonpath);
m_doc.Parse<0>(contentStr.c_str());
CC_BREAK_IF(m_doc.HasParseError());
ret = true;
} while (0);
return ret;
}
ReadString* ReadString::getInstance()
{
if(rs == nullptr)
rs= ReadString::creat("String.json");
return rs;
}
string ReadString::parse(int key)
{
if (!m_doc.IsNull() && m_doc.IsArray()) //判断是不是数组
{
for(unsigned int i=0;i<m_doc.Size();++i)
{
do {
CC_BREAK_IF(m_doc[i].IsNull());
CC_BREAK_IF(m_doc[i]["id"].IsNull());
int i_id = m_doc[i]["id"].GetInt();
CC_BREAK_IF(i_id != key); //这一行是寻找相同的key,找到了才执行下面的语句,找不到就开始下一个循环
CC_BREAK_IF(m_doc[i]["content"].IsNull());
return m_doc[i]["content"].GetString();
}while(0);
}
}
return ""; //没查找到任何对象则返回空字符串
}
上一个博客中的read函数被我改成了parse,其实功能是一样的。但是是不是觉得这样好看很多哈。(好吧,其实还是那么难看)
使用的方法也是一样的:
ReadString::getInstance()->parse(s_iExit)