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

之前一直都是采用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;
}
}

封装游戏配表读取和存储(xml格式);支持行列存取,标题存取的更多相关文章

  1. 用Ajax去读取服务器端的XML格式的数据

    <html> <head></head> <script type="text/javascript"> /*---定义一个全局变量 ...

  2. 在文件中读取、存储Json格式的字符串

    public class Weather { static readonly string FilePath = System.Environment.CurrentDirectory + @&quo ...

  3. C#操作数据表中XML格式的数据

    以前还真没有见过数据表中存储XML格式的数据,刚开始听说的时候,还以为是数据表中有XML的字段类型, 再了解,其实也就是字符串类型的,只不过字符串的格式是XML格式的.确实孤陋寡闻!汗... (可添加 ...

  4. Spring MVC同一方法返回JSON/XML格式

    最近一道面试题,要求同一API接口支持不同格式返回值.一开始是设想通过过滤器(Filter)设置返回值,但是并不可行,因为方法返回值一般都是类型需要做转换,而过滤器则是前置的.另一方面可以通过拦截器的 ...

  5. Android:Xml(读取与存储)

    1.读取XML文件 参数xml是建含xml数据的输入流,List<Person> persons用于存储xml流中的数据. XmlPullParser类的几个方法:next(),nextT ...

  6. hive 压缩全解读(hive表存储格式以及外部表直接加载压缩格式数据);HADOOP存储数据压缩方案对比(LZO,gz,ORC)

    数据做压缩和解压缩会增加CPU的开销,但可以最大程度的减少文件所需的磁盘空间和网络I/O的开销,所以最好对那些I/O密集型的作业使用数据压缩,cpu密集型,使用压缩反而会降低性能. 而hive中间结果 ...

  7. .net数据库连接防注入参数查询 命令执行 读取 备份 导出导入转化XML格式

    ADO.NET是一组类库,让我们通过程序的方式访问数据库.SYSTEM.DATA这个类提供了统一的接口访问Oracle MSSQL Access.像SYSTEM.IO类操作文件一样. **connec ...

  8. Java读取CSV和XML文件方法

    游戏开发中,读取策划给的配置表是必不可少的,我在之前公司,策划给的是xml表来读取,现在公司策划给的是CSV表来读取,其实大同小异,也并不是什么难点,我就简单分享下Java如何读取XML文件和CSV文 ...

  9. Delphi 读取 c# webservice XML的base64编码图片字符串转化图片并显示

    Delphi 读取 c# webservice XML的base64编码图片字符串转化图片并显示 在 开发中遇到应用c#及asp.net的在的webservice 保存图片并以xml文件形式现实出来 ...

随机推荐

  1. php处理表单中的复选框问题以及js实现全选

    做的一个项目中遇到了全选和取消全选的问题,这是一个很普遍的功能,,虽然我们经常用到,但是真正做起来却发现行不通,在网上找了些,大部分都是ie,但是谷歌内核浏览器不能正常实现,所以经过小小的调整,今天就 ...

  2. 云计算之路-阿里云上:14:20-14:55博客后台2台服务器都CPU 100%引发的故障

    非常抱歉,今天下午14:20-14:55期间,由于同一个负载均衡中的2台服务器都出现CPU 100%问题,造成博客后台无法正常访问,由此给您带来了很大很大的麻烦,请您谅解. 博客后台是CPU消耗很低的 ...

  3. cpp(第四章)

    1.索引比数组长度少1: 2.c++中不能数组赋给另一个数组:只能定义时才能使用初始化: 3.c++11中{}内为空,默认赋值为0,而c++中{}如果只对部分初始化,其他部分将被设置为0:c++11使 ...

  4. 关于Oracle、SqlServer 的sql递归查询

    递归查询所有子节点 建人员表  hrmresource 主键     姓名   上级ID 层级关系:- 4      - 3           - 2                - 1      ...

  5. Vulkan Tutorial 17 Rendering and presentation

    操作系统:Windows8.1 显卡:Nivida GTX965M 开发工具:Visual Studio 2017 Setup 这一章节会把之前的所有内容进行整合.我们将会编写drawFrame函数, ...

  6. ubuntu eclipse 建立server 提示coud not load the tomcat server configuration at /opt/apache ...的解决方法

    ubuntu eclipse 建立server 提示coud not load the tomcat server configuration at /opt/apache ...的解决方法 & ...

  7. 什么是nginx?

    1.nginx是一款服务器软件 2.nginx是一个高性能的HTTP和反向代理服务器: 3.nginx是一个代理邮件服务器: 4.nginx还可以实现负载均衡: nginx的优缺点: 优点:可以实现高 ...

  8. python模块之argparse--参数解析

    一.简介: argparse是python用于解析命令行参数和选项的标准模块,用于代替已经过时的optparse模块.argparse模块的作用是用于 解析命令行参数,例如python parseTe ...

  9. ecshop商品页增加编辑器fckeditor

    最近在做ecshop的项目,需要在商品单页中增加一项FCKEditor的文本编辑器,但在ecshop的论坛和百度里搜出的方法,试了好几个都没有用,终于找到一个可以正确使用的,和大家分享. ecshop ...

  10. js实现数据流(日志流,报警信息等)滚动展示,并分页(含实现demo)

    在项目中有遇到,后台向前端推送数据,前端以数据流的形式展示,即来一条我增加一条,类似于日志,报警等信息展示,想必大部分人都有遇到过,本来出于想找一个好的展示方式的心态,因为感觉自己设计的不太好看,结果 ...