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

之前一直都是采用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. Redis 小白指南(三)- 事务、过期、消息通知、管道和优化内存空间

    Redis 小白指南(三)- 事务.过期.消息通知.管道和优化内存空间 简介 <Redis 小白指南(一)- 简介.安装.GUI 和 C# 驱动介绍> 讲的是 Redis 的介绍,以及如何 ...

  2. Spring的<context:property-placeholder.../>在junit中不起作用,失效,解决方法

    大家都知道,我们使用spring框架的时候喜欢把可以配置的变量放入一个properties配置文件中,然后在spring的applicationContext.xml配置文件中加入配置: <co ...

  3. java加密算法入门(一)-算法概念及单向加密

    说起加密,我的第一印象就是电视剧各种密码本破解解密的场景,这两天在看加密相关的东西,做下笔记以便以后查看,也提供给大家个参考. 本文是java加密的第一篇,主要讲述下消息编码Base64以及简单的消息 ...

  4. myBatis动态语句详解

    SQL 映射XML 文件是所有sql语句放置的地方.需要定义一个workspace,一般定义为对应的接口类的路径.写好SQL语句映射文件后,需要在MyBAtis配置文件mappers标签中引用,例如: ...

  5. java.util.concurrent.ExecutionException: org.apache.catalina.LifecycleExcept问题解决方案

    在部署Dynamic Web Project时,如果正确配置web.xml或者标注时,仍然出现以上异常的话,可以尝试以下内容讲解的方法: 首先,双击eclipse中的servers,位置如下图&quo ...

  6. Tenacity——Exception Retry 从此无比简单

    Python 装饰器装饰类中的方法这篇文章,使用了装饰器来捕获代码异常.这种方式可以让代码变得更加简洁和Pythonic. 在写代码的过程中,处理异常并重试是一个非常常见的需求.但是如何把捕获异常并重 ...

  7. javaScript的一些奇妙动画

         今天我给大家讲一下JavaScript中的显示隐藏.淡入淡出的效果 显示与隐藏动画效果 show()方法: show()方法会动态地改变当前元素的高度.宽度和不透明度,最终显示当前元素,此时 ...

  8. docker 架构

    看别的地方大致介绍的,粘贴过来 Docker 使用客户端-服务器 (C/S) 架构模式,使用远程API来管理和创建Docker容器. Docker 容器通过 Docker 镜像来创建. 容器与镜像的关 ...

  9. windows端口占用处理工具

    一.描述 笔者在最近使用tomcat时,老是会遇到这种端口占用的问题,便写了这个小的exe,用于解决windows下的端口占用问题. 好吧,其实是我实在记不住CMD下的那几行命令.这玩意的实现比较简单 ...

  10. 源码安装LNMP环境

    新装CentOS 6.7,安装默认服务版本basic server 安装顺序linux(忽略...)--> Nginx--> Mariadb--> PHP 为了不影响测试效果,首先关 ...