服务热线:13616026886

技术文档 欢迎使用技术文档,我们为你提供从新手到专业开发者的所有资源,你也可以通过它日益精进

位置:首页 > 技术文档 > JAVA > 新手入门 > 基础入门 > 查看文档

使用properties类带来的好处

 

许多开发者抱怨c++不能像java那样绑定properties类。java的properties类内在包含一个文件,该文件用来读写properties类中的属性,可以写成这样形式:<名字>=<数值>(例如:connecttointernet=use ie)。

使用properties类的好处就是你可以很轻松的理解和修改它们。在本文的第一部分中,你将看到我们也可以在c++中使用properties类。本文的第二部分将向你演示通过使用操作符>>和<<把数据保存到properties类中是多么的容易。

现在介绍c++ properties文件的结构。该文件的每一行可以是下面三种情况中的某一种:

空行(认为它是注释中的一部分)

以‘#’ 开始的注释行

‘<名字>=<数值>’行,这是给一个属性赋值的语句

现在让我们再看看properties类的的特点:

注释是持久性的(当保存properties类时,它们不会丢失掉)。注意每一个注释都属于某个属性。在‘<名字>=<数值>’行上的注释行属于该‘<名字>’属性。

当保存properties类后,属性仍然保留自己的位置。

它对各种字符类型都有效:char、wchar_t等等

properties类的使用相当简单:

save():保存属性

has_property(strpropertyname):如果类中有该属性则返回‘真’

string get_property(strpropertyname):返回指定的属性(如果指定属性不存在,则抛出例外)

set_property(strpropertyname, strpropertyvalue):设置给定属性

stringget_property_comment( strpropertyname):返回属于指定属性的注释(如果指定属性的注释不存在,则抛出例外)

set_property_comment(strpropertyname, strpropertycomment):设置指定属性的注释(如果指定属性的注释不存在,则抛出例外)

下面是file_reader_writer类以及相应例子的代码。运行它之后,请查看properties.txt文件。看看访问和修改它是多么容易的一件事。

#include exception>

#include string>

#include sstream>

#include map>

#include vector>

#include fstream>

#include algorithm>

#include functional>

//允许字符串转化

template< class fromchartype, class tochartype>

inline std::basic_string< tochartype> convert_string( const std::basic_string< fromchartype> & strsource)

{

std::basic_string< tochartype> strdest;

int nsourcelen = strsource.length();

strdest.resize( nsourcelen);

for ( int idxchar = 0; idxchar < nsourcelen; idxchar++)

{ strdest[ idxchar] = ( tochartype)strsource[ idxchar]; }

return strdest;

}

// 用于trim_spaces;

template< class chartype>

struct is_char_in_str : public std::binary_function< chartype, std::basic_string< chartype>, bool>

{

bool operator()( chartype ch, const std::basic_string< chartype> & strsource) const

{ return (strsource.find( ch) != std::basic_string< chartype>::npos); }

};

//消除字符串中的空格

template< class chartype>

std::basic_string< chartype> trim_spaces( const std::basic_string< chartype> & strsource)

{

std::basic_string< chartype> strspaces; strspaces += ( chartype)' '; strspaces += ( chartype)'/t';

typedef std::basic_string< chartype> string_type;

string_type::const_iterator

itfirst = std::find_if( strsource.begin(), strsource.end(),

std::not1( std::bind2nd( is_char_in_str< chartype>(), strspaces)));

string_type::const_reverse_iterator

ritlast = std::find_if( strsource.rbegin(), strsource.rend(),

std::not1( std::bind2nd( is_char_in_str< chartype>(), strspaces)));

string_type::const_iterator itlast = &*ritlast;

if ( itfirst <= itlast)

if ( itfirst != strsource.end())
return string_type( itfirst, itlast + 1);

return string_type();

}

// 当读写属性时的例外

class properties_exception : public std::exception

{

public:

properties_exception( const std::string & str) : m_strdescription( str) {}

const char * what() const { return m_strdescription.c_str(); }

private:

std::string m_strdescription;

};

// 从文件中读写属性

template< class chartype>

class file_reader_writer

{

typedef std::basic_string< chartype> string_type;

public:

// ... needed within the basic_properties!

typedef chartype char_type;

public:

file_reader_writer( const char * strfilename)

: m_bisdirty( false), m_strfilename( strfilename) { read_properties(); }

~file_reader_writer() { save(); }

void save()

{ write_properties(); }

bool has_property( const string_type & strpropertyname) const

{

propertiescollection::const_iterator itfound = m_collproperties.find( strpropertyname);

return ( itfound != m_collproperties.end());

}

const string_type & get_property( const string_type & strpropertyname) const

{

propertiescollection::const_iterator itfound = m_collproperties.find( strpropertyname);

if ( itfound != m_collproperties.end())

return itfound->second.m_strvalue;

else

throw properties_exception(

"cound not get property value for '" + convert_string< char_type, char>( strpropertyname) +

"', since this property does not exist.");

}

void set_property( const string_type & strproperty, const string_type & strpropertyvalue)

{

propertiescollection::iterator itfound = m_collproperties.find( strproperty);

if ( itfound == m_collproperties.end())

// 它是一个新的属性

m_aproperties.push_back( strproperty);

m_collproperties[ strproperty].m_strvalue = strpropertyvalue;

m_bisdirty = true;

}

const string_type & get_property_comment( const string_type & strpropertyname) const

{

propertiescollection::const_iterator itfound = m_collproperties.find( strpropertyname);

if ( itfound != m_collproperties.end())

return itfound->second.m_strcomment;

else

throw properties_exception(

"cound not get property comment for '" + convert_string< char_type, char>( strpropertyname) +

"', since this property does not exist.");

}

void set_property_comment( const string_type & strpropertyname, const string_type & strpropertycomment)

{

propertiescollection::iterator itfound = m_collproperties.find( strpropertyname);

if ( itfound != m_collproperties.end())

itfound->second.m_strcomment = strpropertycomment;

else

throw properties_exception(

"cound not set property comment for '" + convert_string< char_type, char>( strpropertyname) +

"', since this property does not exist.");

m_bisdirty = true;

}

private:

static const char_type get_delimeter() { return '='; }

static const char_type get_comment() { return '#'; }

void read_properties()

{

const char delimeter = get_delimeter();

const char comment = get_comment();

std::basic_ifstream< char_type> streamin( m_strfilename.c_str());

string_type strline;

string_type strcomment;

while ( std::getline( streamin, strline))

{

strline = trim_spaces( strline);
bool biscomment = strline.empty() || ( strline[ 0] == comment);

if ( biscomment)

{ strcomment += strline; strcomment += '/n'; }

else

{

int idxdelimeter = strline.find( delimeter);

if ( idxdelimeter != string_type::npos)

{

string_type strpropertyname = strline.substr( 0, idxdelimeter);

string_type strpropertyvalue = strline.substr( idxdelimeter + 1);

strpropertyname = trim_spaces( strpropertyname);

strpropertyvalue = trim_spaces( strpropertyvalue);

m_collproperties.insert(

std::make_pair( strpropertyname, oneproperty( strpropertyvalue, strcomment)));

m_aproperties.push_back( strpropertyname);

strcomment.erase();

}

else

throw properties_exception(

"while reading from file '" + m_strfilename +

"', we encountered an invalid line: /n" + convert_string< char_type, char>( strline));

}
}

m_strlastcomment = strcomment;

}

void write_properties() const

{

if ( !m_bisdirty)

// 无需保存

;return;

const char delimeter = get_delimeter();

std::basic_ofstream< char_type> streamout( m_strfilename.c_str());

propertiesarray::const_iterator

itfirst = m_aproperties.begin(), itlast = m_aproperties.end();

while ( itfirst != itlast)

{

const string_type & strpropertyname = *itfirst;

const oneproperty & property = m_collproperties.find( strpropertyname)->second;

write_property_comment( streamout, property.m_strcomment);

string_type strtowrite = strpropertyname;

strtowrite += ' '; strtowrite += delimeter; strtowrite += ' ';

streamout strtowrite << property.m_strvalue << std::endl;

++itfirst;

}

write_property_comment( streamout, m_strlastcomment);

m_bisdirty = false;

}

void write_property_comment( std::basic_ofstream< char_type> & streamout, const string_type & strcomment) const

{

const char comment = get_comment();

std::basic_stringstream< char_type> streamcomment( strcomment);

string_type strline;

while ( std::getline( streamcomment, strline))

{

if ( !strline.empty())

if ( strline[ 0] == comment)

streamout << strline << std::endl;

else

{

string_type strprefix;

strprefix += comment; strprefix += ' ';

streamout << strprefix << strline << std::endl;

}

else

streamout << std::endl;

}
}

private:

// 我们用来读写的文件

std::string m_strfilename;

//如果自上次保存后属性又有修改则赋值为“真”

mutable bool m_bisdirty;

struct oneproperty

{

oneproperty() {}

oneproperty( const string_type & strvalue, const string_type & strcomment)

: m_strvalue( strvalue), m_strcomment( strcomment) {}

string_type m_strvalue;

string_type m_strcomment;

};

// 属性

typedef std::map< string_type, oneproperty> propertiescollection;

propertiescollection m_collproperties;

// ……确保我们是按同样的次序保存属性

// 读属性

typedef std::vector< string_type> propertiesarray;

propertiesarray m_aproperties;

// 读取所有属性后的注释

string_type m_strlastcomment;

};

下面是用到这个类的一个例子:

#include

int main(int argc, char* argv[])

{

file_reader_writer< char> rw( "properties.txt");

rw.set_property( "app path", "c:/program files/pfs/jokexplorer");

rw.set_property_comment( "app path", "where are we installed?");

rw.set_property( "version", "4.0.0.1");

rw.set_property_comment( "version", "what's our version?");

rw.set_property( "run on startup", "1");

rw.set_property_comment( "run on startup", "are we run, when the computer starts?");

rw.set_property( "automatic logoff minutes", "60");

rw.set_property_comment( "automatic logoff minutes", "when should we deconnect from the server?");

rw.set_property( "connect to internet", "use ie");

rw.set_property_comment( "connect to internet", "how are we to connect to the internet?");

std::cout << "this is how we connect to internet: " << rw.get_property( "connect to internet") << std::endl;

return 0;

}

扫描关注微信公众号