说明:只是个菜鸟,贴出来的目的是希望有大侠指点一下,不足之处,c++学习时间不长,呵。或者帮忙测试一下,共同完善之。
头文件:
//=========================================================
//
// Copyright (c) 2000-2005 TT Technologies,Co. Ltd.
// All Rights Reserved.
//
// Class: CTTXmlFile
//
// Product: TTLibrary
// File : TTXmlFile.h
// Author : http://blog.csdn.net/waterpub
// Created: 2005.03.07 11:30
//
// Description:
// ValueAdded main program for TTLibrary.
// Contact:ShenZhen @ GuangDong
// waterpub@mail.csdn.net
//
//=========================================================
#pragma once
#include "string"
#include "vector"
#include "utility"
#include "algorithm"
using namespace std;
namespace TTLibrary
{
// 维护一个xml条目的类
class CTTXmlItem
{
public:
CTTXmlItem(const string& sItemName);
~CTTXmlItem();
inline bool SetKeyValue(const string& sKey, const string& sValue);
inline bool SetKeyValue(const string& sKey, const int& nValue);
inline bool GetKeyValueString(const string& sKey, string& sValue) const;
inline bool GetKeyValueInt(const string& sKey, int& nValue) const;
inline bool MergeAnother(const CTTXmlItem& xi);
inline string GetItemName() const{ return m_sItemName; }
#ifdef _DEBUG
void Debug();
#endif
private:
const vector<pair<string, string> >* GetKeyVector() const;
private:
string m_sItemName;// 条目名
vector<pair<string, string> > m_KeyVector;// 该条目下的键值列表
friend class CTTXmlFile;
private:
class CTTXmlItemFind// 查找键值的仿函数
{
public:
CTTXmlItemFind(const string& sKey)
{
m_sKey = sKey;
}
bool operator() (const pair<string, string>& XmlItemData)
{
if (XmlItemData.first == m_sKey)
{
return true;
}
else
{
return false;
}
}
private:
stringm_sKey;
};
};
// 加载xml并解析的类
class CTTXmlFile
{
public:
CTTXmlFile(void);
~CTTXmlFile(void);
public:
bool clear();
bool Load(const string& sFileName);
bool Save(const string& sFileName = "");
bool AddItem(const CTTXmlItem& xi);
bool RemoveItem(const string& sItemName);
#ifdef _DEBUG
void Debug();
#endif
private:
bool ParseItem(char* &pStr);
bool ParseKey(char* &pStr, CTTXmlItem& xi);
bool SkipBlank(char* &pStr);
bool SkipEqualChar(char* &pStr);
bool FindWord(char* &pStr, string& sWord);
private:
stringm_sFileName;// 加载的文件名
vector<CTTXmlItem>m_ItemVector;// 条目列表
private:
class CTTXmlItemFind// 查找xml条目列表中有否相同名字的条目的仿函数
{
public:
CTTXmlItemFind(const string& sItemName)
{
m_sItemName = sItemName;
}
bool operator() (const CTTXmlItem& xi)
{
if (xi.GetItemName() == m_sItemName)
{
return true;
}
else
{
return false;
}
}
private:
stringm_sItemName;
};
};
}
实现文件:
#include "StdAfx.h"
#include "ttxmlfile.h"
namespace TTLibrary
{
CTTXmlItem::CTTXmlItem(const string& sItemName)
{
m_sItemName = sItemName;
}
CTTXmlItem::~CTTXmlItem()
{
}
bool CTTXmlItem::SetKeyValue(const string& sKey, const string& sValue)
{
vector<pair<string, string> >::iterator it = find_if(m_KeyVector.begin(), m_KeyVector.end(),
CTTXmlItemFind(sKey));
if (it != m_KeyVector.end())
{
(*it).second = sValue;
}
else
{
pair<string, string> XmlItemData;
XmlItemData.first = sKey;
XmlItemData.second = sValue;
m_KeyVector.push_back(XmlItemData);
}
return true;
}
bool CTTXmlItem::SetKeyValue(const string& sKey, const int& nValue)
{
string sValue;
char szValue[26];
itoa(nValue, szValue, 10);
sValue = szValue;
SetKeyValue(sKey, sValue);
return true;
}
bool CTTXmlItem::GetKeyValueString(const string& sKey, string& sValue) const
{
vector<pair<string, string> >::const_iterator it = find_if(m_KeyVector.begin(), m_KeyVector.end(),
CTTXmlItemFind(sKey));
if (it != m_KeyVector.end())
{
sValue = (*it).second;
return true;
}
else
{
return false;
}
}
bool CTTXmlItem::GetKeyValueInt(const string& sKey, int& nValue) const
{
vector<pair<string, string> >::const_iterator it = find_if(m_KeyVector.begin(), m_KeyVector.end(),
CTTXmlItemFind(sKey));
if (it != m_KeyVector.end())
{
nValue = atoi((*it).second.c_str());
return true;
}
else
{
return false;
}
}
const vector<pair<string, string> >* CTTXmlItem::GetKeyVector() const
{
return &m_KeyVector;
}
bool CTTXmlItem::MergeAnother(const CTTXmlItem& xi)
{
if (xi.GetItemName() == m_sItemName)
{
vector<pair<string, string> >::const_iterator it = (xi.GetKeyVector())->begin();
for(; it != (xi.GetKeyVector())->end(); it++)
{
SetKeyValue((*it).first, (*it).second);
}
}
return true;
}
#ifdef _DEBUG
void CTTXmlItem::Debug()
{
XTRACE(" ===========================\n");
XTRACE(RGB(0, 0, 255), " 条目名:%s\n", m_sItemName.c_str());
vector<pair<string, string> >::iterator it = m_KeyVector.begin();
for(; it != m_KeyVector.end(); it++)
{
XTRACE(" 键:%s,值:%s\n", (*it).first.c_str(), (*it).second.c_str());
}
}
#endif
CTTXmlFile::CTTXmlFile(void)
{
}
CTTXmlFile::~CTTXmlFile(void)
{
}
bool CTTXmlFile::AddItem(const CTTXmlItem& xi)
{
vector<CTTXmlItem>::iterator it = find_if(m_ItemVector.begin(), m_ItemVector.end(),
CTTXmlItemFind(xi.GetItemName()) );
if (it != m_ItemVector.end())
{
(*it).MergeAnother(xi);
return false;
}
else
{
// 没有此条目则添加
m_ItemVector.push_back(xi);
return true;
}
}
bool CTTXmlFile::RemoveItem(const string& sItemName)
{
vector<CTTXmlItem>::iterator it = find_if(m_ItemVector.begin(), m_ItemVector.end(),
CTTXmlItemFind(sItemName) );
if (it != m_ItemVector.end())
{
// 有此条目则删除
m_ItemVector.erase(it);
return true;
}
else
{
return false;
}
}
bool CTTXmlFile::clear()
{
m_ItemVector.clear();
m_sFileName.clear();
return true;
}
bool CTTXmlFile::Load(const string& sFileName)
{
if (sFileName.empty()) return false;
char szDirBuf[MAX_PATH] = "";
GetCurrentDirectory(MAX_PATH, szDirBuf);
strncat(szDirBuf, "\\", strlen("\\"));
strncat(szDirBuf, sFileName.c_str(), sFileName.size());
clear();
m_sFileName = szDirBuf;
FILE* hFile = fopen(m_sFileName.c_str(), "r");
if (NULL == hFile) return false;
string strText;
char* szBuf = new char[1024 + 1];
while (!feof(hFile))
{
int nRead = (int)fread(szBuf, 1, 1024, hFile);
if (nRead > 0)
{
szBuf[nRead] = NULL;
strText += szBuf;
}
}
fclose(hFile);
char* pStr = (char*)strText.c_str();
// 解析文件
while (pStr != NULL)
{
if(!ParseItem(pStr))
break;
}
#ifdef _DEBUG
Debug();
#endif
delete []szBuf;
return true;
}
bool CTTXmlFile::Save(const string& sFileName)
{
return true;
}
// 从文件中解析出一个条目
bool CTTXmlFile::ParseItem(char* &pStr)
{
char* pStart = pStr;
while (*pStart != '<' && *pStart != NULL)
pStart++;
if (*pStart == NULL)
{
pStr = pStart;
return false;// 解析文件结束
}
else
{
pStart++;// 从'<'后面开始
SkipBlank(pStart);
// 解析条目名
string sItemName;
if(FindWord(pStart, sItemName))
{
CTTXmlItem xi(sItemName);
// 解析键值
ParseKey(pStart, xi);
#ifdef _DEBUG
//xi.Debug();
#endif
m_ItemVector.push_back(xi);
}
// 消除对应的'>'字符
SkipBlank(pStart);
if (*pStart == '>') pStart++;
pStr = pStart;
return true;
}
}
bool CTTXmlFile::ParseKey(char* &pStr, CTTXmlItem& xi)
{
string sKey;
string sValue;
while (FindWord(pStr, sKey))
{
if( SkipEqualChar(pStr))
{
if( FindWord(pStr, sValue))
{
xi.SetKeyValue(sKey, sValue);
}
}
}
SkipBlank(pStr);
return true;
}
bool CTTXmlFile::SkipBlank(char* &pStr)
{
while ((*pStr > 0 && *pStr < 33))
pStr++;
return true;
}
bool CTTXmlFile::SkipEqualChar(char* &pStr)
{
SkipBlank(pStr);
if (*pStr == '=')
{
pStr++;
return true;
}
else
return false;
}
// 字符串,不能为 '<' 或 '>' 或 '='
bool CTTXmlFile::FindWord(char* &pStr, string& sWord)
{
SkipBlank(pStr);
char* pStart = pStr;
while ((*pStart >= 33 || *pStart < 0) && *pStart != '<' && *pStart != '>' && *pStart != '=')
pStart++;
if (pStart == pStr)
{
pStr = pStart;
return false;
}
else
{
string strTemp(pStr, pStart);
sWord = strTemp;
pStr = pStart;
return true;
}
}
#ifdef _DEBUG
void CTTXmlFile::Debug()
{
XTRACE("***********************************************\n");
XTRACE(RGB(255, 0, 0), "文件名:%s\n", m_sFileName.c_str());
XTRACE("***********************************************\n");
vector<CTTXmlItem>::iterator it = m_ItemVector.begin();
for(; it!= m_ItemVector.end(); it++)
{
(*it).Debug();
}
}
#endif
}
测试文件:test.ini,如下(写的很乱,作为加强测试,):
fdsafd
fdsafds
< ><aaaaa=sfd
< >>
< aa>fdsafds
< tt aaa = bbb >
< test >
<name Name1=ccc name2 = ddd>
测试代码:
CTTXmlFile ttxf;
ttxf.Load("skin2.ini");