在MFC里面用了一下iniparser类,发现功能不健全,又重新封装了一下,删除了上一篇日志。
MFC和boost的兼容性很烂,我为了省事专门给CString做了重载和特化。
头文件(VS一直不支持export关键字,非常蛋疼):
1 /************************************************************************/
2 /* Instruction: CIniParser类主要是封装了boost::property_tree::ini_parser中的几个
3 函数,用来操纵ini配置文件。ini文件用于比较简单的程序配置,因此该类被写成了单例。
4 在C++11下,该类是线程安全的,否则不是。
5 Note: 由于该类只和STL及boost打交道,因此使用了STL命名规范。注意property_tree会抛出异常,
6 这里需要捕获异常,并返回错误码。
7 */
8 /************************************************************************/
9 #ifndef CTI_SDK_USING_MFC_INI_PARSER_H
10 #define CTI_SDK_USING_MFC_INI_PARSER_H
11
12 #include <string>
13 #include <map>
14 #include <memory>
15 #include <boost/property_tree/ptree.hpp>
16 #include <boost/property_tree/ini_parser.hpp>
17 //模板实现所需
18 #include <boost/property_tree/exceptions.hpp>
19 #include <boost/lexical_cast.hpp>
20
21 class CIniParser :
22 private boost::noncopyable
23 {
24 public:
25 enum IniErrNo
26 {
27 kNoErr=0,
28 kNotFound=1,
29 kNotModified=2,
30 kCanNotCreateFile=3,
31 kOtherErr=10
32 };
33 static CIniParser& GetInstance( //获得单例
34 const std::wstring& full_filename=L"config.ini");//文件的相对/绝对路径+文件名
35
36 ~CIniParser(void){}
37 template<typename T>
38 int Get(const std::wstring& section_name,const std::wstring& property_name,
39 T *result)const;
40 template<typename T>
41 int Put(const std::wstring& section_name,const std::wstring& property_name,
42 const T& value);
43 int PutMaps(const std::wstring& section_name,
44 const std::map<std::wstring,std::wstring>& property_value_map);
45 //#ifdef _MFC_VER
46 // //为方便使用,提供CString接口
47 template<typename T>
48 int Get(const CString& secitonName,const CString& propertyName,
49 T* result)const;
50 //CString非标准,lexical_cast会失败,因此需要特化
51 template<>
52 int Get<CString>(const CString& secitonName,const CString& propertyName,
53 CString* result)const;
54 template<typename T>
55 int Put(const CString& sectionName,const CString& propertyName,
56 const T& value);
57 template<>
58 int Put<CString>(const CString& sectionName,const CString& propertyName,
59 const CString& value);
60 int PutMaps(const CString& sectionName,
61 const std::map<CString,CString>& propertyValueMap);
62 //#endif //!_MFC_VER
63
64 private:
65 CIniParser(const std::wstring& full_filename);
66 std::string filename_;
67 boost::property_tree::wptree pt_;
68 };
69
70 //模板函数的实现,由于VS不支持export关键字,模板函数只能定义在头文件中(考虑写在另一个文件,然后include)
71
72 template<typename T>
73 int CIniParser::Get(const std::wstring& section_name,
74 const std::wstring& property_name,
75 T *result)const
76 {
77 std::wstring node(section_name+L"."+property_name);
78 try
79 {
80 *result=pt_.get<T>(node);
81 }catch(boost::property_tree::ptree_bad_data& e)
82 {
83 std::cout<<e.data<std::string>()<<std::endl;
84 return CIniParser::kNotFound;
85 }catch(boost::property_tree::ptree_bad_path& e)
86 {
87 std::cout<<e.what()<<std::endl;
88 return CIniParser::kCanNotCreateFile;
89 }
90 catch(...)
91 {
92 return CIniParser::kOtherErr;
93 }
94 return 0;
95 }
96
97 template<typename T>
98 int CIniParser::Get(const CString& secitonName,
99 const CString& propertyName,
100 T *result)const
101 {
102 return Get(wstring(secitonName.GetString()),propertyName.GetString(),result);
103 }
104
105 template<>
106 int CIniParser::Get<CString>(const CString& secitonName,const CString& propertyName,
107 CString* result)const
108 {
109 std::wstring temp;
110 int err=Get(std::wstring(secitonName.GetString()),
111 propertyName.GetString(),
112 &temp);
113 *result=temp.c_str();
114 return err;
115 }
116 template<typename T>
117 int CIniParser::Put(const std::wstring& section_name,
118 const std::wstring& property_name,
119 const T& value)
120 {
121 std::wstring node(section_name+L"."+property_name);
122 int err=0;
123 try
124 {
125 pt_.put(node,value);
126 write_ini(filename_,pt_);
127 }
128 catch(boost::property_tree::ptree_bad_data& e)
129 {
130 err=CIniParser::kNotModified;
131 std::wcout<<e.data<std::wstring>()<<std::endl;
132 }
133 catch(boost::property_tree::ini_parser_error& e)
134 {
135 err=CIniParser::kNotModified;
136 std::cout<<"Line "<<e.line()
137 <<", file name: "<<e.filename()
138 <<", message: "<<e.message()
139 <<std::endl;
140 }
141 catch(...)
142 {
143 return CIniParser::kOtherErr;
144 }
145 return err;
146 }
147 template<typename T>
148 int CIniParser::Put(const CString& sectionName,const CString& propertyName,
149 const T& value)
150 {
151 return Put(wstring(sectionName.GetString()),propertyName.GetString(),value);
152 }
153
154 template<>
155 int CIniParser::Put<CString>(const CString& sectionName,const CString& propertyName,
156 const CString& value)
157 {
158 //指定实例函数
159 return Put(std::wstring(sectionName.GetString())
160 ,propertyName.GetString(),value.GetString());
161 }
162
163 #endif // !CTI_SDK_USING_MFC_INI_PASER_H
实现文件:
1 #include "IniParser.h"
2 #include <fstream>
3 #include <boost/property_tree/exceptions.hpp>
4 #include <boost/lexical_cast.hpp>
5 #include "tools.h"
6 using namespace std;
7 using namespace boost::property_tree;
8 using namespace boost;
9
10 //Warn: 这种方法在C++11前是行不通的!可以使用boost::call_once完成
11 CIniParser& CIniParser::GetInstance(const std::wstring& full_filename)
12 {
13 static CIniParser instance(full_filename);
14 return instance;
15 }
16
17
18 int CIniParser::PutMaps(const std::wstring& section_name,
19 const std::map<std::wstring,std::wstring>& property_value_map)
20 {
21 int err=0;
22 for(auto pairs:property_value_map)
23 {
24 try
25 {
26 pt_.put(section_name+L"."+pairs.first,pairs.second);
27 }
28 catch(ptree_bad_data& e)
29 {
30 err=CIniParser::kNotModified;
31 wcout<<L"write error:"<<e.data<wstring>()<<endl;
32 }
33 }
34 try
35 {
36 write_ini(filename_,pt_);
37 }
38 catch(ini_parser_error& e)
39 {
40 err=CIniParser::kNotModified;
41 cout<<"Line "<<e.line()
42 <<", file name: "<<e.filename()
43 <<", message: "<<e.message()
44 <<endl;
45 }
46 return err;
47 }
48
49 int CIniParser::PutMaps( const CString& sectionName,
50 const std::map<CString,CString>& propertyValueMap )
51 {
52 map<wstring,wstring> temp_map;
53 for(auto pairs:propertyValueMap)
54 {
55 temp_map[pairs.first.GetString()]=pairs.second.GetString();
56 }
57 return PutMaps(sectionName.GetString(),temp_map);
58 }
59
60 CIniParser::CIniParser( const std::wstring& full_filename)
61 {
62 wstring_to_string(full_filename,&filename_);
63 wfstream file(filename_,ios::in);
64 if (!file)
65 {
66 file.clear();
67 file.open(filename_,ios::out);
68 //这里可能抛出异常
69 assert(file);
70 file.close();
71 }
72 read_ini(filename_,pt_);
73 }
使用的工具函数:
1 /************************************************************************/
2 /* Instruction: 本文件主要包含了一些自己常用的工具函数,方便其他函数引用
3 */
4 /************************************************************************/
5 #ifndef CTI_SDK_USING_MFC_TOOLS_H
6 #define CTI_SDK_USING_MFC_TOOLS_H
7 #include <string>
8 //UNICODE转换辅助函数
9 //仅供内部使用
10 static int ANSIToUnicode(const char *src,int srcCount,wchar_t *dest,int destCount);
11 static int UnicodeToANSI(const wchar_t *src,int srcCount,char *dest,int destCount);
12 //for MFC only
13 #if defined(_MFC_VER)
14 int CStringAToCStringW(const CStringA& src,CStringW *dest);
15 int CStringWToCStringA(const CStringW& src,CStringA *dest);
16 CString GetIPFromDWORD(const DWORD& dw);
17 DWORD MakeIPToDWORD(const CString& ip);
18 #endif
19 //只涉及标准库,使用STL命名约定
20 int string_to_wstring(const std::string& src,std::wstring *dest);
21 int wstring_to_string(const std::wstring& src,std::string *dest);
22
23 int GetUniqueName(const TCHAR *prefix,TCHAR *out,int outCount);
24 #endif // !CTI_SDK_USING_MFC_TOOLS_H
实现:
1 #include "tools.h"
2 #include <boost/lexical_cast.hpp>
3
4 using namespace std;
5 using namespace boost;
6
7 int ANSIToUnicode(const char *src,int srcCount,wchar_t *dest,int destCount)
8 {
9 assert(src && dest);
10 assert(destCount >= srcCount);
11 #ifdef WIN32
12 #include <stringapiset.h>
13 int err=MultiByteToWideChar(CP_ACP,0,src,-1,dest,destCount*sizeof(dest[0]));
14 if (err==0)
15 {
16 err=static_cast<int>(GetLastError());
17 }
18 else
19 {
20 err=0;
21 }
22 return err;
23 #else
24 setlocale(LC_ALL,"");
25 int err=mbstowcs(dest,src,destCount*sizeof(dest[0]));
26 setlocale(LC_ALL,"C");
27 return err;
28 #endif // WIN32
29 }
30 int UnicodeToANSI(const wchar_t *src,int srcCount,char *dest,int destCount)
31 {
32 assert(src && dest);
33 assert(destCount >= srcCount);
34 #ifdef WIN32
35 int err=WideCharToMultiByte(CP_ACP,0,src,-1,dest,destCount,NULL,NULL);
36 if (err==0)
37 {
38 err=static_cast<int>(GetLastError());
39 }
40 else
41 {
42 err=0;
43 }
44 return err;
45 #else
46 setlocale(LC_ALL,"");
47 int err=wcstombs(dest,src,destCount);
48 setlocale(LC_ALL,"C");
49 return err;
50 #endif
51 }
52 int CStringAToCStringW(const CStringA& src,CStringW *dest)
53 {
54 int length;
55 #ifdef WIN32
56 length=MultiByteToWideChar(CP_ACP,0,src,-1,NULL,0)+1;
57 #else
58 length=mbstowcs(NULL,src,0)+1;
59 #endif // WIN32
60 wchar_t *destbuffer=new wchar_t[length];
61 int err=ANSIToUnicode(src,src.GetLength(),destbuffer,length);
62 dest->Format(L"%s",destbuffer);
63 delete[] destbuffer;
64 return err;
65 }
66 int CStringWToCStringA(const CStringW& src,CStringA *dest)
67 {
68 int length;
69 #ifdef WIN32
70 length=WideCharToMultiByte(CP_ACP,0,src,-1,NULL,0,NULL,NULL)+1;
71 #else
72 length=wcstombs(NULL,src,0)*2+1;
73 #endif // WIN32
74 char *destbuffer=new char[length];
75 int err=UnicodeToANSI(src,src.GetLength(),destbuffer,length);
76 dest->Format("%s",destbuffer);
77 delete[] destbuffer;
78 return err;
79 }
80 //TODO: 应该先实现标准的,再使用非标准的调用标准,这里懒得修改了
81 int string_to_wstring(const string& src,wstring *dest)
82 {
83 CStringW destbuffer;
84 int err=CStringAToCStringW(src.c_str(),&destbuffer);
85 dest->assign(destbuffer.GetString());
86 destbuffer.ReleaseBuffer();
87 return err;
88 }
89 int wstring_to_string(const wstring& src,string *dest)
90 {
91 CStringA destbuffer;
92 int err=CStringWToCStringA(src.c_str(),&destbuffer);
93 dest->assign(destbuffer.GetString());
94 destbuffer.ReleaseBuffer();
95 return err;
96 }
97
98 //TODO: 完善错误处理
99 int GetUniqueName(const TCHAR *prefix,TCHAR *out,int outCount)
100 {
101 int errcode=0;
102 TCHAR tszTemplate[MAX_PATH]={0};
103 errcode=_tcscat_s(tszTemplate,MAX_PATH*sizeof(TCHAR),_T("XXXXXX"));
104 assert(outCount >= _countof(tszTemplate));
105 errcode=_tmktemp_s(tszTemplate);
106 errcode=_tcscpy_s(out,outCount*sizeof(TCHAR),tszTemplate);
107 return errcode;
108 }
109
110 CString GetIPFromDWORD( const DWORD& dw )
111 {
112 WORD hw=HIWORD(dw);
113 WORD lw=LOWORD(dw);
114 BYTE ip1stSection=HIBYTE(hw);
115 BYTE ip2ndSection=LOBYTE(hw);
116 BYTE ip3rdSection=HIBYTE(lw);
117 BYTE ip4thSection=LOBYTE(lw);
118 CString result;
119 result.Format(_T("%d.%d.%d.%d"),ip1stSection,ip2ndSection,ip3rdSection,
120 ip4thSection);
121 return result;
122 }
123
124 DWORD MakeIPToDWORD( const CString& ip )
125 {
126 CString ipSections[4];
127 CString temp;
128 int pos=0,i=0;
129 temp=ip.Tokenize(_T("."),pos);
130 while (temp!=_T(""))
131 {
132 VERIFY(i<4);
133 ipSections[i++]=temp;
134 temp=ip.Tokenize(_T("."),pos);
135 }
136 BYTE ip1stSection=_ttoi(ipSections[0].GetString());
137 BYTE ip2ndSection=_ttoi(ipSections[1].GetString());
138 BYTE ip3rdSection=_ttoi(ipSections[2].GetString());
139 BYTE ip4thSection=_ttoi(ipSections[3].GetString());
140 //注意高低位顺序
141 WORD hw=MAKEWORD(ip2ndSection,ip1stSection);
142 WORD lw=MAKEWORD(ip4thSection,ip3rdSection);
143 DWORD result=MAKELONG(lw,hw);
144
145 return result;
146 }
这几天写MFC程序,感觉最麻烦的就是unicode和ansi的转换。
C++最令人的讨厌的特性之一就是不缺省支持unicode,最讨厌的特性之二是没有好的GUI框架。
如果可以的话,还是直接用Qt最简单。C++的哲学确实偏向学院派,不管是ace,boost还是poco,甚至stl,单独拿出来学习,感觉都很惊艳,
但是在工业项目中间使用,就感觉各种别扭……
原文链接: https://www.cnblogs.com/livewithnorest/archive/2013/05/04/3060311.html
欢迎关注
微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍
原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/87130
非原创文章文中已经注明原地址,如有侵权,联系删除
关注公众号【高性能架构探索】,第一时间获取最新文章
转载文章受原作者版权保护。转载请注明原作者出处!