cocos2d-x 使用TinyXML2存储数据:

最近换了cocos2d-x劳动节版,原来版本的CCUserDefault使用的是libxml2,劳动节版的使用了TinyXML2(貌似2.1.2就换了),有国外开发者说,他升级引擎后什么都没干,游戏在安卓上的加载时间从20秒缩短到了5秒。

因为CCUserDefault没有提供对节点属性的操作,所以我就简单写了一下针对节点内容以及节点属性的操作,简单封装,与大家分享下,基本该有的操作应该是全了【为了让读者方便使用,有两个方法是介绍使用的,你如果用本库,可以删除:createXMLFile();readXML()】,废话不多说,提供源码【目前只是简单使用,后期非逐渐完善,添加各种方法,对数据进行加密,就像《CCUserDefault加密》一文中的,可能表现为:《工具库:UtilTools》一文中的方式】……

FDTinyXML2.h

//
// FDTinyXML2.h
// RunnerEditor
//
// Created by firedragonpzy on 13-5-3.
//
//
#ifndef __RunnerEditor__FDTinyXML2__
#define __RunnerEditor__FDTinyXML2__
#include "support/tinyxml2/tinyxml2.h"
#include "cocos2d.h"
#include "platform/CCFileUtils.h"
#include "TempObject.h"
#include "RConfig.h"
#include <fstream>
USING_NS_CC;
using namespace tinyxml2;
using namespace std;
class FDTinyXML2 : public CCObject{
public:
bool init();
CREATE_FUNC(FDTinyXML2);
bool createXMLFile();
void readXML();
bool createXMLFileFromArray(CCArray *array,CCArray *array1);
bool readXMLToArray(CCArray* &array,cocos2d::CCArray *&array1);
private:
string m_sFilePath;
string m_sBackUpFilePath;
bool isXMLFileExist();
bool backupXMLFile();
bool copyFile(const char*pszFile, const char* newFile);
void groundNodeToArray(XMLElement *ground,CCArray *&array);
void eleNodeToArray(XMLElement *ele,CCArray *&array1);
};
#endif /* defined(__RunnerEditor__FDTinyXML2__) */





FDTinyXML2.cpp

//
// FDTinyXML2.cpp
// RunnerEditor
//
// Created by firedragonpzy on 13-5-3.
//
//
#include "FDTinyXML2.h"
// root name of xml
#define FDTinyXML2_ROOT_NAME "firedragonpzy"
#define XML_FILE_NAME "firedragonpzy.xml"
#define XML_BACKUP_FILE_NAME "firedragonpzy.bak"
#define XML_FIRST_NODE "grounds"
#define XML_SECOND_NODE "barriers"
bool FDTinyXML2::init()
{
if (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32)//if you don't
{
m_sFilePath = CCFileUtils::sharedFileUtils()->fullPathForFilename(XML_FILE_NAME);
m_sBackUpFilePath = CCFileUtils::sharedFileUtils()->fullPathForFilename(XML_BACKUP_FILE_NAME);
}else
{
m_sFilePath = CCFileUtils::sharedFileUtils()->getWritablePath() + XML_FILE_NAME;
m_sBackUpFilePath = CCFileUtils::sharedFileUtils()->getWritablePath() + XML_BACKUP_FILE_NAME;
}
return true;
}
// This is a demo, if you use my lib,you can delete this method createXMLFile()
bool FDTinyXML2::createXMLFile()
{
bool bRet = false;
tinyxml2::XMLDocument *pDoc = new tinyxml2::XMLDocument();
if (NULL == pDoc) {
return false;
}
tinyxml2::XMLDeclaration *pDeclaration = pDoc->NewDeclaration("xml version=\"1.0\" encoding=\"UTF-8\"");
if (NULL == pDeclaration) {
return false;
}
pDoc->LinkEndChild(pDeclaration);
tinyxml2::XMLElement *pRootEle = pDoc->NewElement(FDTinyXML2_ROOT_NAME);
if (NULL == pRootEle) {
return false;
}
pDoc->LinkEndChild(pRootEle);
tinyxml2::XMLElement *subGroundGrass = pDoc->NewElement("groundGrass");
tinyxml2::XMLText *content = pDoc->NewText("content:groudText");
subGroundGrass->LinkEndChild(content);
pRootEle->LinkEndChild(subGroundGrass);
tinyxml2::XMLElement *subGroundSoil = pDoc->NewElement("groundSoil");
subGroundSoil->SetAttribute("soil-attribute", "text:soil");
pRootEle->LinkEndChild(subGroundSoil);
bRet = tinyxml2::XML_SUCCESS == pDoc->SaveFile(m_sFilePath.c_str());
if (pDoc) {
delete pDoc;
}
return bRet;
}
// This is a demo, if you use my lib,you can delete this method readXML()
void FDTinyXML2::readXML()
{
tinyxml2::XMLDocument *pDoc = new tinyxml2::XMLDocument();
tinyxml2::XMLElement *rootNode = NULL;
tinyxml2::XMLElement *curNode = NULL;
const tinyxml2::XMLAttribute *curAttribute = NULL;
do {
unsigned long nSize;
const char *pXmlBuffer = (const char*)CCFileUtils::sharedFileUtils()->getFileData(m_sFilePath.c_str(), "rb", &nSize);
if (NULL == pXmlBuffer) {
break;
}
pDoc->Parse(pXmlBuffer);
rootNode = pDoc->RootElement();
if (NULL == rootNode) {
break;
}
curNode = rootNode->FirstChildElement();
XMLElement *secondNode = curNode->NextSiblingElement();
CCLog("---------------Test------------------");
CCLog("GetText():%s",secondNode->GetText());
CCLog("Name():%s",secondNode->Name());
CCLog("Value():%s",secondNode->Value());
CCLog("---------------Test------------------");
curAttribute = curNode->FirstAttribute();
while (NULL != curNode) {
CCLog("GetText():%s",curNode->GetText());
CCLog("Value():%s",curNode->Value());
while (NULL != curAttribute) {
CCLog("curAttribute->Name():%s",curAttribute->Name());
CCLog("curAttribute->Value():%s",curAttribute->Value());
curAttribute = curAttribute->Next();
}
curNode = curNode->NextSiblingElement();
if (curNode) {
curAttribute = curNode->FirstAttribute();
}
CCLog("---------------END----------------");
}
if (pDoc) {
delete pDoc;
}
} while (0);
}
// Determine if xml exists.
bool FDTinyXML2::isXMLFileExist()
{
CCLog("%s",m_sFilePath.c_str());
FILE *fp = fopen(m_sFilePath.c_str(), "r");
bool bRet = false;
if (fp) {
bRet = true;
fclose(fp);
}
return bRet;
}
bool FDTinyXML2::backupXMLFile()
{
bool bRet = false;
if (isXMLFileExist()) {
if (copyFile(m_sFilePath.c_str(), m_sBackUpFilePath.c_str())) {
bRet = true;
}else
{
bRet = false;
}
}else
{
bRet = false;
CCLog("no file exists!");
}
return bRet;
}
bool FDTinyXML2::copyFile(const char *pszFile, const char *newFile)
{
ifstream input;
ofstream output;
input.open(pszFile,ios::binary);
if (input.fail()) {
input.close();
output.close();
return false;
}
output.open(newFile,ios::binary);
if (output.fail()) {
input.close();
output.close();
return false;
}else
{
output<<input.rdbuf();
output.close();
input.close();
return true;
}
}
bool FDTinyXML2::createXMLFileFromArray(cocos2d::CCArray *array,CCArray *array1)
{
bool bRet = false;
if (isXMLFileExist()) {
if (remove(m_sFilePath.c_str()))
{
return false;
}
}
XMLDocument *pDoc = new XMLDocument();
if (NULL == pDoc) {
return false;
}
XMLDeclaration *pDeclaration = pDoc->NewDeclaration("xml version=\"1.0\" encoding=\"UTF-8\"");
if (NULL == pDeclaration) {
return false;
}
pDoc->LinkEndChild(pDeclaration);
XMLElement *pRootEle = pDoc->NewElement(FDTinyXML2_ROOT_NAME);
if (NULL == pRootEle) {
return false;
}
pDoc->LinkEndChild(pRootEle);
TempObject *tempObj = NULL;
XMLElement *subElement = NULL;
if (array ) {
int count = array->count();
if (count > 0) {
XMLElement *firstNode = pDoc->NewElement(XML_FIRST_NODE);
if (NULL != firstNode) {
pRootEle->LinkEndChild(firstNode);
}else
{
return false;
}
for (int i = 0; i < count; i++) {
tempObj = (TempObject*)array->objectAtIndex(i);
GroundBarrierStruct groundStruct = tempObj->getGroundBarrier();
subElement = pDoc->NewElement(groundStruct.bType.c_str());
subElement->SetAttribute(XML_POSX, groundStruct.posx);
subElement->SetAttribute(XML_POSY, groundStruct.posy);
subElement->SetAttribute(XML_FLAG, groundStruct.flag);
firstNode->LinkEndChild(subElement);
}
}
}
if (array1 ) {
int count = array1->count();
if (count > 0) {
XMLElement *secondNode = pDoc->NewElement(XML_SECOND_NODE);
if (NULL != secondNode) {
pRootEle->LinkEndChild(secondNode);
}else
{
return false;
}
for (int i = 0; i < count; i++) {
tempObj = (TempObject*)array1->objectAtIndex(i);
EleBarrierStuct eleStruct = tempObj->getEleBarrier();
subElement = pDoc->NewElement(eleStruct.bType.c_str());
subElement->SetAttribute(XML_POSX, eleStruct.posx);
subElement->SetAttribute(XML_POSY, eleStruct.posy);
subElement->SetAttribute(XML_FLAG, eleStruct.flag);
secondNode->LinkEndChild(subElement);
}
}
}
bRet = tinyxml2::XML_SUCCESS == pDoc->SaveFile(m_sFilePath.c_str());
if (pDoc) {
delete pDoc;
}
// this method usets to back up the file,if you don't need,you can delete.
backupXMLFile();
return bRet;
}
bool FDTinyXML2::readXMLToArray(cocos2d::CCArray *&array,cocos2d::CCArray *&array1)
{
bool bRet = false;
if (isXMLFileExist()) {
do {
XMLDocument *xmlDoc = new XMLDocument();
// const XMLAttribute *curAttribute = NULL;
unsigned long nSize;
const char* xmlBuffer = (const char*)CCFileUtils::sharedFileUtils()->getFileData(m_sFilePath.c_str(), "rb", &nSize);
if (NULL == xmlBuffer) {
return false;
}
xmlDoc->Parse(xmlBuffer);
delete [] xmlBuffer;
XMLElement *rootNode = xmlDoc->RootElement();
if (NULL == rootNode) {
return false;
}
// first element
XMLElement *firstNode = rootNode->FirstChildElement();
if (NULL == firstNode) {
return false;
}
XMLElement *subFirstNode = firstNode->FirstChildElement();
if (NULL == subFirstNode) {
return false;
}
if (strncmp(firstNode->Name(),XML_FIRST_NODE,strlen(XML_FIRST_NODE)) == 0) {
groundNodeToArray(subFirstNode,array);
}else if (strncmp(firstNode->Name(),XML_SECOND_NODE,strlen(XML_SECOND_NODE)) == 0)
{
eleNodeToArray(subFirstNode, array1);
}
// next element
XMLElement *secondNode = firstNode->NextSiblingElement();
if (NULL == secondNode) {
return true;
}
XMLElement *subSecondNode = secondNode->FirstChildElement();
if (NULL == subSecondNode) {
return true;
}
if (strncmp(secondNode->Name(),XML_FIRST_NODE,strlen(XML_FIRST_NODE)) == 0) {
groundNodeToArray(subSecondNode,array);
}else if (strncmp(secondNode->Name(),XML_SECOND_NODE,strlen(XML_SECOND_NODE)) == 0)
{
eleNodeToArray(subSecondNode, array1);
}
} while (0);
bRet = true;
}else
{
bRet = false;
}
return bRet;
}
void FDTinyXML2::groundNodeToArray(XMLElement *ground,CCArray *&array)
{
const XMLAttribute *curAttribute = NULL;
TempObject *obj = NULL;
GroundBarrierStruct groundStruct;
while (NULL != ground) {
curAttribute = ground->FirstAttribute();
if (strncmp(curAttribute->Name(), XML_POSX,strlen(XML_POSX)) == 0) {
groundStruct.posx = atof(curAttribute->Value());
}
groundStruct.bType = ground->Name();
obj = TempObject::create();
while (NULL != curAttribute) {
if (strncmp(curAttribute->Name(), XML_POSX,strlen(XML_POSX)) == 0) {
groundStruct.posx = atof(curAttribute->Value());
}else if (strncmp(curAttribute->Name(), XML_POSY,strlen(XML_POSY)) == 0)
{
groundStruct.posy = atof(curAttribute->Value());
}else if (strncmp(curAttribute->Name(), XML_FLAG,strlen(XML_FLAG)) == 0)
{
groundStruct.flag = atoi(curAttribute->Value());
}
obj->setGroundBarrier(groundStruct);
curAttribute = curAttribute->Next();
}
array->addObject(obj);
ground = ground->NextSiblingElement();
}
}
void FDTinyXML2::eleNodeToArray(tinyxml2::XMLElement *ele, cocos2d::CCArray *&array1)
{
EleBarrierStuct eleStruct;
TempObject *obj = NULL;
const XMLAttribute *curAttribute = NULL;
while (NULL != ele) {
curAttribute = ele->FirstAttribute();
eleStruct.bType = ele->Name();
obj = TempObject::create();
while (NULL != curAttribute) {
if (strncmp(curAttribute->Name(), XML_POSX,strlen(XML_POSX)) == 0) {
eleStruct.posx = atof(curAttribute->Value());
}else if (strncmp(curAttribute->Name(), XML_POSY, strlen(XML_POSY)) == 0)
{
eleStruct.posy = atof(curAttribute->Value());
}else if (strncmp(curAttribute->Name(), XML_FLAG, strlen(XML_FLAG)) == 0)
{
eleStruct.flag = atoi(curAttribute->Value());
}
obj->setEleBarrier(eleStruct);
curAttribute = curAttribute->Next();
}
array1->addObject(obj);
ele = ele->NextSiblingElement();
}
}



暂且提供这些,后续补充,忘大家多多提供宝贝意见……

注意事项:

在win中开发的时候:

1、使用XMLDocument的时候要添加tinyxml2命名空间,否则error:不明确的符号

2、目前来说tinyxml2还不能直接引用处理,需要自己include

2013、05、09【v1.0】

2013、05、10【v1.1】更新:

1、修改了读取的bug

2、调整了win上面文件存储的位置,v1.0存储在可读路径下,如果打包exe,无法获取xml文件。现在存储在Resouces路径下……

Demo下载链接:https://github.com/firedragonpzy/FD_Libs.git


你可能感兴趣的:(cocos2d-x 使用TinyXML2存储数据:)