COCOS学习--数据交换格式(17)

本文介绍了数据交换格式,包括CSV、XML和JSON。详细讲解了CSV的基本概念和解码方法,提到了XML的两种解析方式SAX和DOM,并重点介绍了COCOS中基于DOM的XML解析库tinyxml2。最后,阐述了JSON格式,并展示了使用rapidjson进行解码和编码的示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

CSV数据交换格式

两个程序之间如何交换数据,用什么格式,常见的有CSV,XML,JSON。

1.CSV介绍

关于CSV的介绍请参考维基https://zh.wikipedia.org/wiki/%E9%80%97%E5%8F%B7%E5%88%86%E9%9A%94%E5%80%BC

2.CSV格式解码

解码函数

__Array* CSVParser::parse(const char* fileName)
{
	auto sharedFileUtils = FileUtils::getInstance();

	string pathKey = sharedFileUtils->fullPathForFilename(fileName);//转换为全路径

	string content = sharedFileUtils->getStringFromFile(pathKey);//读取
	__String* contentStr  = __String::create(content);//std::string转换为_string格式

	__Array* rows = contentStr->componentsSeparatedByString("\n");//以换行符为间隔读取

	__Array* ret = __Array::createWithCapacity(rows->count());

	Ref *obj = nullptr;
	CCARRAY_FOREACH(rows, obj)//遍历rows
	{
		auto fieldStr = static_cast<__String*>(obj);
		__Array* fields = fieldStr->componentsSeparatedByString(",");//以逗号为间隔读取
		ret->addObject(fields);
	}
	return ret;
}

记事本格式

读取完输出

XML数据交换格式

1.XML格式 https://zh.wikipedia.org/wiki/XML

2.解析

目前流行的主要有SAX和DOM。

2.1 SAX解析

SAX是一种基于事件驱动的解析方式。从上到下读取文档,但无法写入,且程序编写有点难度,有点就是速度快

例子:

通过下面几个函数可以实现读取XML文件

private: 

	std::string startElementName;//记录开始元素 
	cocos2d::ValueMap row;

public:
	
	static XmlParser * createWithFile(const char *fileName); 
   
    bool initWithFile(const char* xmlName); 
  
    //SAXDelegator 的3个回调方法
    virtual void startElement(void *ctx, const char *name, const char **atts); 
    virtual void endElement(void *ctx, const char *name); 
    virtual void textHandler(void *ctx, const char *ch, int len); 

2.2 DOM解析

DOM称为文档对象模型,DOM模型是将XML文档作为树状结构进行分析。

虽然因为一次性读入内存导致解析速度变慢,但缺可以修改XML文档。

COCOS封装了XML解析库tinyxml2.是基于C++语言的DOM函数的解析库,可以读写XML文档。

主要函数parse(),解析XML数据

void XmlParser::parse()
{
	tinyxml2::XMLDocument xmlDoc;

	xmlDoc.Parse(content.c_str());

	tinyxml2::XMLElement *root = xmlDoc.RootElement();

	tinyxml2::XMLElement *note =root->FirstChildElement("Note");  

	while(note){

		row = ValueMap();

		//取id属性
		const tinyxml2::XMLAttribute *att =  note->FirstAttribute();
		std::pair<std::string,Value> idPair("id",Value(att->Value()));
		row.insert(idPair);

		//取CDate元素内容
		tinyxml2::XMLElement *dateElement =note->FirstChildElement("CDate"); 
		row["CDate"] = Value(dateElement->GetText());
		
		//取Content元素内容
		tinyxml2::XMLElement *contentElement =note->FirstChildElement("Content");
		row["Content"] = Value(contentElement->GetText());

		//取UserID元素内容
		tinyxml2::XMLElement *userIDElement =note->FirstChildElement("UserID");
		row["UserID"] = Value(userIDElement->GetText());

		list.push_back(Value(row));

		if(note->NextSibling() == nullptr){
			break;
		}else {
			note = note->NextSibling()->ToElement();
		}

	}

}

再输出

JSON数据交换格式

格式如图

1.1 rapidjson解码

解码函数decode

void JsonParser::decode()
{
	rapidjson::Document document;
	document.Parse<0>(content.c_str());

	//解析错误
	CCASSERT(!document.HasParseError(), "Parsing to document failure.");

	log("Parsing to document succeeded.");

	CC_ASSERT(document.IsObject() && document.HasMember("Record"));

	const rapidjson::Value &records= document["Record"]; //读取中文的数组 
	//判断是不是数组 
	CC_ASSERT(records.IsArray());

	for(unsigned int i = 0; i < records.Size();i++) //如果不是数组,这一行会报错 
	{ 
		row = ValueMap();

		//获得一条记录对象
		const rapidjson::Value &record = records[i]; 

		//判断这个record有没有ID键 
		CC_ASSERT(record.HasMember("ID"));
		const rapidjson::Value &val_id = record["ID"]; 
		//判断ID类型 
		CC_ASSERT(val_id.IsString());
		row["id"] = Value(val_id.GetString()); 

		//判断这个record有没有CDate键 
		CC_ASSERT(record.HasMember("CDate"));
		const rapidjson::Value &val_CDate = record["CDate"]; 
		//判断CDate类型 
		CC_ASSERT(val_CDate.IsString());
		row["CDate"] = Value(val_CDate.GetString()); 

		//判断这个record有没有Content键 
		CC_ASSERT(record.HasMember("Content"));
		const rapidjson::Value &val_Content = record["Content"]; 
		//判断Content类型 
		CC_ASSERT(val_Content.IsString());		
		row["Content"] = Value(val_Content.GetString()); 

		//判断这个record有没有UserID键 
		CC_ASSERT(record.HasMember("UserID"));
		const rapidjson::Value &val_UserID = record["UserID"]; 
		//判断UserID类型 
		CC_ASSERT(val_UserID.IsString());
		row["UserID"] = Value(val_UserID.GetString()); 

		list.push_back(Value(row));
	}
}

1.2 rapidjson编码

	ValueVector listData ;

	auto createValueMap1 =[&](){
		ValueMap ret;
		ret["ID"] = Value(1);
		ret["CDate"] = Value("2014-3-10");
		ret["Content"] = "发布iOSBook0";
		ret["UserID"] = "tony";
		return ret;
	};
	listData.push_back(Value(createValueMap1()));

	auto createValueMap2 =[&](){
		ValueMap ret;
		ret["ID"] = Value(2);
		ret["CDate"] = Value("2014-3-11");
		ret["Content"] = "发布iOSBook1";
		ret["UserID"] = "tony";
		return ret;
	};
	listData.push_back(Value(createValueMap2()));

	auto createValueMap3 =[&](){
		ValueMap ret;
		ret["ID"] = Value(3);
		ret["CDate"] = Value("2014-3-12");
		ret["Content"] = "发布iOSBook2";
		ret["UserID"] = "tony";
		return ret;
	};

	listData.push_back(Value(createValueMap3()));

	auto createValueMap4 =[&](){
		ValueMap ret;
		ret["ID"] = Value(4);
		ret["CDate"] = Value("2014-3-13");
		ret["Content"] = "发布iOSBook3";
		ret["UserID"] = "tony";
		return ret;
	};
	listData.push_back(Value(createValueMap4()));

	auto createValueMap5 =[&](){
		ValueMap ret;
		ret["ID"] = Value(5);
		ret["CDate"] = Value("2014-3-14");
		ret["Content"] = "发布iOSBook4";
		ret["UserID"] = "tony";
		return ret;
	};
	listData.push_back(Value(createValueMap5()));

	auto createValueMap6  =[&](){
		ValueMap ret;
		ret["ID"] = Value(6);
		ret["CDate"] = Value("2014-3-15");
		ret["Content"] = "发布iOSBook5";
		ret["UserID"] = "tony";
		return ret;
	};
	listData.push_back(Value(createValueMap6()));

	auto parser = JsonParser::createWithArray(listData);//加入数据
	parser->encode();//编码
void JsonParser::encode()
{
	rapidjson::Document document;
	document.SetObject();
	rapidjson::Document::AllocatorType& allocator = document.GetAllocator();

	rapidjson::Value array(rapidjson::kArrayType);
	
	for (auto& v: listData)
	{
		ValueMap row = v.asValueMap();

		rapidjson::Value object(rapidjson::kObjectType);

		rapidjson::Value v_id;
		v_id.SetString(row["ID"].asString().c_str(), allocator);
		object.AddMember("ID", v_id, allocator);

		rapidjson::Value v_Date;
		v_Date.SetString(row["CDate"].asString().c_str(), allocator);
		object.AddMember("CDate", v_Date, allocator);
		
		rapidjson::Value v_Content;
		v_Content.SetString(row["Content"].asString().c_str(), allocator);
		object.AddMember("Content", v_Content, allocator);

		rapidjson::Value v_UserID;
		v_UserID.SetString(row["UserID"].asString().c_str(), allocator);
		object.AddMember("UserID", v_UserID, allocator);

		array.PushBack(object, allocator);
	}

	document.AddMember("ResultCode", 0, allocator);
	document.AddMember("Record", array, allocator);

	rapidjson::StringBuffer buffer;
	rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);

	document.Accept(writer);

	auto out = buffer.GetString();

	log("out: %s", out);

}

 

 

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值