以前做java项目的时候,需要一些配置参数,java提供了Properties 类 来操作,存储配置,挺方便的,现在既然在看c++,就想着用c++来实现这么一个类。
要求:
1.支持注释,单行,多行注释都行
2.简单的key/value 模型
3.获取,修改,清空,存储操作等
接口头文件:properties.h
#ifndef PROPERTIES_H #define PROPERTIES_H #include <string> #include <map> namespace huals{ class Properties{ private //配置文件路径 std::string filepath; //配置选项存储pair<key,value> std::map<std::string,std::string> pps; //注释存储pair<key,annotation> std::map<std::string,std::string> ann; public: Properties(std::string file); std::string Get_property(std::string key); void Set_property(std::string key,std::string value); int Save(); void Clear(); //测试用,输出配置文件的内容 void Print(); }; } #include "properties.cpp" #endif
具体实现:properties.cpp
#include <iostream> #include <fstream> #include <string> #include <map> #include <sstream> #include <cstring> namespace huals{ //may throw error Properties::Properties(std::string file):filepath(file){ std::fstream in; in.open(file.c_str()); if(!in) return ; std::string line; //注释 std::string annotation; while(getline(in,line)){ std::string key; std::string value; /* *去掉字符串头尾空字符 */ int start,end; start=line.find_first_not_of(" "); end=line.find_last_not_of(" "); if(start<0) start=0; line=line.substr(start,end-start+1); //如果以#开头,则为配置文件 if('#'==line[0]){ annotation+=line+" "; }else{ start=line.find_first_of("="); key=line.substr(0,start); value=line.substr(start+1,line.size()-start); pps.insert(make_pair(key,value)); /* *注释是在配置的前面,如果注释不为空,则插入注释map */ if(!annotation.empty()){ ann.insert(make_pair(key,annotation)); annotation.clear(); } } } in.close(); } //if the key not in map, return empty string std::string Properties::Get_property(std::string key){ std::string value; std::map<std::string,std::string>::iterator it=pps.find(key); if(it!=pps.end()) value=it->second; return value; } /* *设置配置项,key不存在,将会添加 */ void Properties::Set_property(std::string key,std::string value){ pps[key]=value; } /* *存档,写入配置文件 */ int Properties::Save(){ std::ofstream out; out.open(filepath.c_str(),std::ofstream::out); std::map<std::string,std::string>::iterator temp,it=pps.begin(); while(it!=pps.end()){ std::string line; temp=ann.find(it->first); if(temp!=ann.end()) out<<temp->second; line+=it->first+"="; line+=it->second; out<<line<<std::endl; it++; } out.close(); return 0; } /* *清空配置项,注意清空后调用Save()才有效 */ void Properties::Clear(){ pps.clear(); ann.clear(); } //配置文件输出测试 void Properties::Print(){ std::map<std::string,std::string>::iterator temp,it=pps.begin(); while(it!=pps.end()){ std::string line; temp=ann.find(it->first); if(temp!=ann.end()) std::cout<<temp->second; line+=it->first+"="; line+=it->second; std::cout<<line<<std::endl; it++; } } }
经过测试,这个类基本满足要求。
待改进:
1.中文支持,没有特别设置编码这些信息,楼主在fedora 系统编码utf-8下测试是支持中文的
2.异常处理,读写配置文件都可能发生异常,这个需要改进
3.线程安全,如果有多个线程同时读写配置文件,需重写此类
下面顺便写一个简单c++ 整数转成字符串东东,不用itoa这种偏c的东西
#include <iostream> #include <sstream> #include <string> int main(void){ ostringstream oss; int a=12; oss<<a; std::string str=oss.str(); std::cout<<str<<std::endl; return 0; }
over,好好学习,daydayup!