以下是转载于网上的一个很好的config文件的实现,留存以备案
1 //Config.h 2 #pragma once 3 4 #include <string> 5 #include <map> 6 #include <iostream> 7 #include <fstream> 8 #include <sstream> 9 10 11 /* 12 * \brief Generic configuration Class 13 * 14 */ 15 class Config { 16 // Data 17 protected: 18 std::string m_Delimiter; //!< separator between key and value 19 std::string m_Comment; //!< separator between value and comments 20 std::map<std::string,std::string> m_Contents; //!< extracted keys and values 21 22 typedef std::map<std::string,std::string>::iterator mapi; 23 typedef std::map<std::string,std::string>::const_iterator mapci; 24 // Methods 25 public: 26 27 Config( std::string filename,std::string delimiter = "=",std::string comment = "#" ); 28 Config(); 29 template<class T> T Read( const std::string& in_key ) const; //!<Search for key and read value or optional default value, call as read<T> 30 template<class T> T Read( const std::string& in_key, const T& in_value ) const; 31 template<class T> bool ReadInto( T& out_var, const std::string& in_key ) const; 32 template<class T> 33 bool ReadInto( T& out_var, const std::string& in_key, const T& in_value ) const; 34 bool FileExist(std::string filename); 35 void ReadFile(std::string filename,std::string delimiter = "=",std::string comment = "#" ); 36 37 // Check whether key exists in configuration 38 bool KeyExists( const std::string& in_key ) const; 39 40 // Modify keys and values 41 template<class T> void Add( const std::string& in_key, const T& in_value ); 42 void Remove( const std::string& in_key ); 43 44 // Check or change configuration syntax 45 std::string GetDelimiter() const { return m_Delimiter; } 46 std::string GetComment() const { return m_Comment; } 47 std::string SetDelimiter( const std::string& in_s ) 48 { std::string old = m_Delimiter; m_Delimiter = in_s; return old; } 49 std::string SetComment( const std::string& in_s ) 50 { std::string old = m_Comment; m_Comment = in_s; return old; } 51 52 // Write or read configuration 53 friend std::ostream& operator<<( std::ostream& os, const Config& cf ); 54 friend std::istream& operator>>( std::istream& is, Config& cf ); 55 56 protected: 57 template<class T> static std::string T_as_string( const T& t ); 58 template<class T> static T string_as_T( const std::string& s ); 59 static void Trim( std::string& inout_s ); 60 61 62 // Exception types 63 public: 64 struct File_not_found { 65 std::string filename; 66 File_not_found( const std::string& filename_ = std::string() ) 67 : filename(filename_) {} }; 68 struct Key_not_found { // thrown only by T read(key) variant of read() 69 std::string key; 70 Key_not_found( const std::string& key_ = std::string() ) 71 : key(key_) {} }; 72 }; 73 74 75 /* static */ 76 template<class T> 77 std::string Config::T_as_string( const T& t ) 78 { 79 // Convert from a T to a string 80 // Type T must support << operator 81 std::ostringstream ost; 82 ost << t; 83 return ost.str(); 84 } 85 86 87 /* static */ 88 template<class T> 89 T Config::string_as_T( const std::string& s ) 90 { 91 // Convert from a string to a T 92 // Type T must support >> operator 93 T t; 94 std::istringstream ist(s); 95 ist >> t; 96 return t; 97 } 98 99 100 /* static */ 101 template<> 102 inline std::string Config::string_as_T<std::string>( const std::string& s ) 103 { 104 // Convert from a string to a string 105 // In other words, do nothing 106 return s; 107 } 108 109 110 /* static */ 111 template<> 112 inline bool Config::string_as_T<bool>( const std::string& s ) 113 { 114 // Convert from a string to a bool 115 // Interpret "false", "F", "no", "n", "0" as false 116 // Interpret "true", "T", "yes", "y", "1", "-1", or anything else as true 117 bool b = true; 118 std::string sup = s; 119 for( std::string::iterator p = sup.begin(); p != sup.end(); ++p ) 120 *p = toupper(*p); // make string all caps 121 if( sup==std::string("FALSE") || sup==std::string("F") || 122 sup==std::string("NO") || sup==std::string("N") || 123 sup==std::string("0") || sup==std::string("NONE") ) 124 b = false; 125 return b; 126 } 127 128 129 template<class T> 130 T Config::Read( const std::string& key ) const 131 { 132 // Read the value corresponding to key 133 mapci p = m_Contents.find(key); 134 if( p == m_Contents.end() ) throw Key_not_found(key); 135 return string_as_T<T>( p->second ); 136 } 137 138 139 template<class T> 140 T Config::Read( const std::string& key, const T& value ) const 141 { 142 // Return the value corresponding to key or given default value 143 // if key is not found 144 mapci p = m_Contents.find(key); 145 if( p == m_Contents.end() ) return value; 146 return string_as_T<T>( p->second ); 147 } 148 149 150 template<class T> 151 bool Config::ReadInto( T& var, const std::string& key ) const 152 { 153 // Get the value corresponding to key and store in var 154 // Return true if key is found 155 // Otherwise leave var untouched 156 mapci p = m_Contents.find(key); 157 bool found = ( p != m_Contents.end() ); 158 if( found ) var = string_as_T<T>( p->second ); 159 return found; 160 } 161 162 163 template<class T> 164 bool Config::ReadInto( T& var, const std::string& key, const T& value ) const 165 { 166 // Get the value corresponding to key and store in var 167 // Return true if key is found 168 // Otherwise set var to given default 169 mapci p = m_Contents.find(key); 170 bool found = ( p != m_Contents.end() ); 171 if( found ) 172 var = string_as_T<T>( p->second ); 173 else 174 var = value; 175 return found; 176 } 177 178 179 template<class T> 180 void Config::Add( const std::string& in_key, const T& value ) 181 { 182 // Add a key with given value 183 std::string v = T_as_string( value ); 184 std::string key=in_key; 185 trim(key); 186 trim(v); 187 m_Contents[key] = v; 188 return; 189 }
1 // Config.cpp 2 3 #include "Config.h" 4 5 using namespace std; 6 7 8 Config::Config( string filename, string delimiter, 9 string comment ) 10 : m_Delimiter(delimiter), m_Comment(comment) 11 { 12 // Construct a Config, getting keys and values from given file 13 14 std::ifstream in( filename.c_str() ); 15 16 if( !in ) throw File_not_found( filename ); 17 18 in >> (*this); 19 } 20 21 22 Config::Config() 23 : m_Delimiter( string(1,'=') ), m_Comment( string(1,'#') ) 24 { 25 // Construct a Config without a file; empty 26 } 27 28 29 30 bool Config::KeyExists( const string& key ) const 31 { 32 // Indicate whether key is found 33 mapci p = m_Contents.find( key ); 34 return ( p != m_Contents.end() ); 35 } 36 37 38 /* static */ 39 void Config::Trim( string& inout_s ) 40 { 41 // Remove leading and trailing whitespace 42 static const char whitespace[] = " \n\t\v\r\f"; 43 inout_s.erase( 0, inout_s.find_first_not_of(whitespace) ); 44 inout_s.erase( inout_s.find_last_not_of(whitespace) + 1U ); 45 } 46 47 48 std::ostream& operator<<( std::ostream& os, const Config& cf ) 49 { 50 // Save a Config to os 51 for( Config::mapci p = cf.m_Contents.begin(); 52 p != cf.m_Contents.end(); 53 ++p ) 54 { 55 os << p->first << " " << cf.m_Delimiter << " "; 56 os << p->second << std::endl; 57 } 58 return os; 59 } 60 61 void Config::Remove( const string& key ) 62 { 63 // Remove key and its value 64 m_Contents.erase( m_Contents.find( key ) ); 65 return; 66 } 67 68 std::istream& operator>>( std::istream& is, Config& cf ) 69 { 70 // Load a Config from is 71 // Read in keys and values, keeping internal whitespace 72 typedef string::size_type pos; 73 const string& delim = cf.m_Delimiter; // separator 74 const string& comm = cf.m_Comment; // comment 75 const pos skip = delim.length(); // length of separator 76 77 string nextline = ""; // might need to read ahead to see where value ends 78 79 while( is || nextline.length() > 0 ) 80 { 81 // Read an entire line at a time 82 string line; 83 if( nextline.length() > 0 ) 84 { 85 line = nextline; // we read ahead; use it now 86 nextline = ""; 87 } 88 else 89 { 90 std::getline( is, line ); 91 } 92 93 // Ignore comments 94 line = line.substr( 0, line.find(comm) ); 95 96 // Parse the line if it contains a delimiter 97 pos delimPos = line.find( delim ); 98 if( delimPos < string::npos ) 99 { 100 // Extract the key 101 string key = line.substr( 0, delimPos ); 102 line.replace( 0, delimPos+skip, "" ); 103 104 // See if value continues on the next line 105 // Stop at blank line, next line with a key, end of stream, 106 // or end of file sentry 107 bool terminate = false; 108 while( !terminate && is ) 109 { 110 std::getline( is, nextline ); 111 terminate = true; 112 113 string nlcopy = nextline; 114 Config::Trim(nlcopy); 115 if( nlcopy == "" ) continue; 116 117 nextline = nextline.substr( 0, nextline.find(comm) ); 118 if( nextline.find(delim) != string::npos ) 119 continue; 120 121 nlcopy = nextline; 122 Config::Trim(nlcopy); 123 if( nlcopy != "" ) line += "\n"; 124 line += nextline; 125 terminate = false; 126 } 127 128 // Store key and value 129 Config::Trim(key); 130 Config::Trim(line); 131 cf.m_Contents[key] = line; // overwrites if key is repeated 132 } 133 } 134 135 return is; 136 } 137 bool Config::FileExist(std::string filename) 138 { 139 bool exist= false; 140 std::ifstream in( filename.c_str() ); 141 if( in ) 142 exist = true; 143 return exist; 144 } 145 146 void Config::ReadFile( string filename, string delimiter, 147 string comment ) 148 { 149 m_Delimiter = delimiter; 150 m_Comment = comment; 151 std::ifstream in( filename.c_str() ); 152 153 if( !in ) throw File_not_found( filename ); 154 155 in >> (*this); 156 }
1 //main.cpp 2 #include "Config.h" 3 int main() 4 { 5 int port; 6 std::string ipAddress; 7 std::string username; 8 std::string password; 9 const char ConfigFile[]= "config.txt"; 10 Config configSettings(ConfigFile); 11 12 port = configSettings.Read("port", 0); 13 ipAddress = configSettings.Read("ipAddress", ipAddress); 14 username = configSettings.Read("username", username); 15 password = configSettings.Read("password", password); 16 std::cout<<"port:"<<port<<std::endl; 17 std::cout<<"ipAddress:"<<ipAddress<<std::endl; 18 std::cout<<"username:"<<username<<std::endl; 19 std::cout<<"password:"<<password<<std::endl; 20 21 return 0; 22 }
config.txt的文件内容:
ipAddress=10.10.90.125
port=3001
username=mark
password=2d2df5a
编译运行输出:
port:3001
ipAddress:10.10.90.125
username:mark
password:2d2df5a
原文地址:http://cooker.iteye.com/blog/777455