封装游戏配表读取和存储(xml格式);支持行列存取,标题存取

做服务器肯定会涉及到游戏配表,而读取游戏配表是一个必备技能;

之前一直都是采用TinyXml直接读,匹配字符串,每次加个表都是一大坨代码,看着也是心累;

因此利用了闲暇的时间封装了一个 xml配置表 读取类;

1.支持 按照 列*行的读取方法

2.支持 按照 "标题"*行的读取方法

3.支持 按照 列*行的修改

4.支持 按照 "标题"*行的修改

//例子用的xml , 库用的是 tinyxml 2.5.3

<?xml version="1.0" encoding="gbk" standalone="yes" ?>
<config>
    <Quest Quest_ID="1" Quest_Star="1" Quest_Limit="0" Quest_Type="6" Quest_TarID="0" Quest_Tar_Num="100" Award_Type="2" Award_ID="1" Awa_Num="5000" Quest_Des="击杀%d" bModify="0" bNew="0" />
    <Quest Quest_ID="2" Quest_Star="1" Quest_Limit="0" Quest_Type="6" Quest_TarID="0" Quest_Tar_Num="500" Award_Type="2" Award_ID="1" Awa_Num="10000" Quest_Des="击杀%d" bModify="0" bNew="0" />
    <Quest Quest_ID="3" Quest_Star="1" Quest_Limit="0" Quest_Type="10" Quest_TarID="0" Quest_Tar_Num="3" Award_Type="2" Award_ID="1" Awa_Num="6000" Quest_Des="击杀%d" bModify="0" bNew="0" />
    <Quest Quest_ID="4" Quest_Star="1" Quest_Limit="0" Quest_Type="10" Quest_TarID="0" Quest_Tar_Num="5" Award_Type="2" Award_ID="1" Awa_Num="8000" Quest_Des="击杀%d" bModify="0" bNew="0" />
    <Quest Quest_ID="5" Quest_Star="1" Quest_Limit="0" Quest_Type="11" Quest_TarID="0" Quest_Tar_Num="1" Award_Type="2" Award_ID="1" Awa_Num="10000" Quest_Des="击杀%dBOSS" bModify="0" bNew="0" />
    <Quest Quest_ID="6" Quest_Star="1" Quest_Limit="0" Quest_Type="11" Quest_TarID="0" Quest_Tar_Num="2" Award_Type="2" Award_ID="1" Awa_Num="15000" Quest_Des="击杀%dBOSS" bModify="0" bNew="0" />
    <Quest Quest_ID="7" Quest_Star="1" Quest_Limit="0" Quest_Type="6" Quest_TarID="0" Quest_Tar_Num="100" Award_Type="2" Award_ID="2" Awa_Num="10" Quest_Des="击杀%d" bModify="0" bNew="0" />
    <Quest Quest_ID="8" Quest_Star="1" Quest_Limit="0" Quest_Type="6" Quest_TarID="0" Quest_Tar_Num="500" Award_Type="2" Award_ID="2" Awa_Num="25" Quest_Des="击杀%d" bModify="0" bNew="0" />
    <Quest Quest_ID="9" Quest_Star="1" Quest_Limit="0" Quest_Type="10" Quest_TarID="0" Quest_Tar_Num="3" Award_Type="2" Award_ID="2" Awa_Num="15" Quest_Des="击杀%d赏金" bModify="0" bNew="0" />
    <Quest Quest_ID="10" Quest_Star="1" Quest_Limit="0" Quest_Type="10" Quest_TarID="0" Quest_Tar_Num="5" Award_Type="2" Award_ID="2" Awa_Num="20" Quest_Des="击杀%d赏金" bModify="0" bNew="0" />
    <Quest Quest_ID="11" Quest_Star="1" Quest_Limit="0" Quest_Type="11" Quest_TarID="0" Quest_Tar_Num="1" Award_Type="2" Award_ID="2" Awa_Num="25" Quest_Des="击杀%d" bModify="0" bNew="0" />
    <Quest Quest_ID="12" Quest_Star="1" Quest_Limit="0" Quest_Type="11" Quest_TarID="0" Quest_Tar_Num="2" Award_Type="2" Award_ID="2" Awa_Num="40" Quest_Des="击杀%d" bModify="0" bNew="0" />
</config>

 下面就直接上代码;

#pragma once
#pragma warning(disable:4786)
#pragma warning(disable:4503)

#include "tinyxml.h"
#include <map>
#include <string>

using namespace std;
class CRowStr{
public:
	CRowStr(int row,string title)
	{
		_row=row;
		_title=title;
	}

	bool operator<( const  CRowStr& a) const
	{
		if(this->_row<a._row)
			return true;
		else
		return false;
	};
	
	int _row;//行
	string _title;//标题
};

typedef map<CRowStr, string> mpCfgRow;
typedef map<int, mpCfgRow*> mpCfgList;

//默认从第1列开始读取
#define ROWBEGIN 1

//默认从第1行开始读取
#define LINEBEGIN 1

//非元素模式从1000开始
#define NEXTBEGIN 1000

//暂时不支持非元素模式
class CXmlFileReader
{
public:
	CXmlFileReader(const char* _filename,const int _flag=1);
	~CXmlFileReader();

	//获取第line行的_title字段的数据
	char* GetValueByTitle(const char*_title/*字段*/, const int _line=LINEBEGIN/*行数*/);
	//获取第line行的_row列数据
	char* GetValueByRow(const int _row=ROWBEGIN/*列数*/, const int _line=LINEBEGIN/*行数*/);
	
	//设置第line行的_title字段的数据
	bool SetValueByTitle(const char *_value/*内容*/,const char*_title/*字段*/,const int _line=LINEBEGIN/*行数*/);
	//设置第line行的_row列数据
	bool SetValueByRow(const char *_value/*内容*/,const int _row=ROWBEGIN/*列数*/,const int _line=LINEBEGIN/*行数*/);
	
	int GetLines();//获取行数
	int GetRows();//获取列数
	
private:
	void _loadFile();
	void _clearMap();
	void _example();//例子
	
private:
	bool					m_load_ok;
	string 					m_path;
	int						m_Flag;
	int						m_Maxlines;
	int						m_Maxrows;
	mpCfgList*				m_config_map;
};

 下面是.cpp文件

#include "XmlControl.h"

CXmlFileReader::CXmlFileReader(const char* _filename,const int _flag)
{
    m_Maxlines=0;
    m_Maxrows=0;
    m_config_map = new mpCfgList;
    m_path = string(_filename);
    m_Flag = _flag;
    _loadFile();
}

CXmlFileReader::~CXmlFileReader()
{
    _clearMap();
}

void CXmlFileReader::_example()
{
    //用法
    string filePath = "D:\\Quest.xml";
    CXmlFileReader Reader(filePath.c_str());

    //读取
	string _desRowOld(Reader.GetValueByRow(10,2));
	string _desTitleOld(Reader.GetValueByTitle("Quest_Des",3));
    //设置节点值
	Reader.SetValueByTitle("Testtitle","Quest_Des",3);
	Reader.SetValueByRow("Testrow",10,2);
    //读取
	string _desRowNew(Reader.GetValueByRow(10,2));
	string _desTitleNew(Reader.GetValueByTitle("Quest_Des",3));
}

int CXmlFileReader::GetLines()
{
    if(!m_load_ok)
        return 0;
    return m_Maxlines;
}

int CXmlFileReader::GetRows()
{
    if(!m_load_ok)
        return 0;
    return m_Maxrows;
}

char* CXmlFileReader::GetValueByTitle(const char* title,const int line)
{
    if (!m_load_ok)
        return NULL;
    char* value = NULL;
    mpCfgList::iterator itLine = m_config_map->find(line);
    if(itLine == m_config_map->end())
        return NULL;
    mpCfgRow* mpRowValue = itLine->second;
    mpCfgRow::iterator itValue = mpRowValue->begin();
    for (; itValue != mpRowValue->end(); itValue++){
        const CRowStr key=itValue->first;
        if (key._title==string(title)){
            value = (char*) itValue->second.c_str();
            break;
        }
    }
    return value;
}

char* CXmlFileReader::GetValueByRow(const int row, const int line)
{
    if (!m_load_ok)
        return NULL;
    char* value = NULL;
    mpCfgList::iterator itLine = m_config_map->find(line);
    if(itLine == m_config_map->end())
        return NULL;
    mpCfgRow* mpRowValue = itLine->second;
    mpCfgRow::iterator itValue = mpRowValue->begin();
    for (; itValue != mpRowValue->end(); itValue++){
        const CRowStr key = itValue->first;
        if(key._row == row){
            value = (char*) itValue->second.c_str();
            break;
        }
    }
    return value;
}

bool CXmlFileReader::SetValueByTitle(const char * value,const char* title,const int line)
{
    TiXmlDocument _doc;
    int _curline=line;
    int _flag = m_Flag;
	if(!_doc.LoadFile(m_path.c_str())||!title||!value)
        return false;
	//改xml值
    TiXmlElement* _pelement = _doc.RootElement(); //root
	while(_flag--){
		_pelement = _pelement->FirstChildElement(); //指向下一个
	}
	while(_pelement){
		TiXmlAttribute* _attributeOfStudent = _pelement->FirstAttribute(); //获得每一级的各种属性
		if(--_curline>0){
            _pelement = _pelement->NextSiblingElement();
            continue;
		}
		while(_attributeOfStudent){
            if(string(_attributeOfStudent->Name())==title){
				_attributeOfStudent->SetValue(value);
                break;
			}
			_attributeOfStudent = _attributeOfStudent->Next();//指向下一个元素
		}
        break;
	}
    //保存
    if(!_doc.SaveFile(m_path.c_str()))
        return false;
    
    //改内存里的值
    mpCfgList::iterator itLine = m_config_map->find(line);
    if(itLine == m_config_map->end())
        return NULL;
    mpCfgRow* mpRowValue = itLine->second;
    mpCfgRow::iterator itValue = mpRowValue->begin();
    for (; itValue != mpRowValue->end(); itValue++){
        const CRowStr key = itValue->first;
		string _strtile = string(title);
        if (key._title==_strtile){
            string _newValue = string(value);
            itValue->second = _newValue;
            break;
        }
    }
	return true;
}

bool CXmlFileReader::SetValueByRow(const char * value,const int row,const int line)
{
    TiXmlDocument _doc;
    int _curline=line;
    int _currow=row;
    int _flag = m_Flag;
	if(!_doc.LoadFile(m_path.c_str())||!value)
        return false;
	//改xml值
    TiXmlElement* _pelement = _doc.RootElement();
	while(_flag--){
		_pelement = _pelement->FirstChildElement();
	}
	while(_pelement){
		TiXmlAttribute* _attributeOfStudent = _pelement->FirstAttribute();
		if(--_curline>0){
            _pelement = _pelement->NextSiblingElement();
            continue;
		}
		while(_attributeOfStudent){
            if(--_currow>0){
                _attributeOfStudent = _attributeOfStudent->Next();
                continue;
    		}
			_attributeOfStudent->SetValue(value);
            break;
		}
        break;
	}
    //保存
    if(!_doc.SaveFile(m_path.c_str()))
        return false;
    
    //改内存里的值
    mpCfgList::iterator itLine = m_config_map->find(line);
    if(itLine == m_config_map->end())
        return NULL;
    mpCfgRow* mpRowValue = itLine->second;
    mpCfgRow::iterator itValue = mpRowValue->begin();
    for (; itValue != mpRowValue->end(); itValue++){
        const CRowStr key = itValue->first;
        if(key._row==row){
            string _newValue = string(value);
            itValue->second = _newValue;
            break;
        }
    }
	return true;
}

void CXmlFileReader::_clearMap()
{
    if(!m_config_map)
        return;
    mpCfgList::iterator it = m_config_map->begin();
    for (; it != m_config_map->end(); it++){
		delete it->second;
    }
    
    delete m_config_map;
	m_config_map = NULL;
}

void CXmlFileReader::_loadFile()
{
    int _flag = m_Flag;
	TiXmlDocument _doc;
    int _line=LINEBEGIN;
	//int _nxline=NEXTBEGIN;
    int _row=ROWBEGIN;
	if(!_doc.LoadFile(m_path.c_str())){
        m_load_ok=false;
        return;
    }
    TiXmlElement* _pelement=_doc.RootElement(); //root
	while(_flag--){
		_pelement=_pelement->FirstChildElement();//指向下一个大节点
	}
    switch (_pelement->Type())  
    {  
        case TiXmlText::DOCUMENT:break;  
        case TiXmlText::DECLARATION:break;  
        case TiXmlText::TEXT:break;  
        case TiXmlText::UNKNOWN:break;  		
        case TiXmlText::COMMENT:break;  
        case TiXmlText::ELEMENT:
		{
			while(_pelement){
				TiXmlAttribute* _attributeOfStudent=_pelement->FirstAttribute(); //获得每一级的各种属性
				if (_attributeOfStudent)
				{
					mpCfgRow* mpRowValue= new mpCfgRow();
                    int _rowdex=ROWBEGIN;
					while (_attributeOfStudent){
                        CRowStr _rowinfo(_rowdex++,string(_attributeOfStudent->Name()));
						mpRowValue->insert(make_pair(_rowinfo,string(_attributeOfStudent->Value())));//存储第_line行的所有列
						_attributeOfStudent=_attributeOfStudent->Next();//指向下一个元素
						++_row;
					}
					_pelement=_pelement->NextSiblingElement();
					m_config_map->insert(make_pair(_line++,mpRowValue));//存储_line行的所有元素
				}
				else
				{
					/*mpCfgRow* mpRowValue= new mpCfgRow();
					mpRowValue->insert(make_pair(string(_pelement->Value()),
						string(_pelement->FirstChild()->Value())));//存储第_line行的所有列
					_pelement=_pelement->NextSiblingElement();
					m_config_map->insert(make_pair(_nxline++,mpRowValue));//存储_line行的所有元素
					*/
				}
				
			}
			m_Maxlines=_line-LINEBEGIN;
			m_Maxrows=(_row-ROWBEGIN)/m_Maxlines;
			m_load_ok=true;
		}
        break;
    }
}

 

posted @ 2016-08-09 16:13  蓝辰进击者  阅读(480)  评论(0编辑  收藏  举报