(2)[转载]C++本地化locale和国际化facet

引自:http://blog.csdn.net/HewpKanXue/archive/2007/04/27/1587545.aspx

关于本地化的学习心得阅读书籍

本地化都是通过locale和facet这两个类来实现的

所有基本的国际化方法都在标准facet中提供。facet提供文化差异的服务和信息。

名次解释:国际化:尽量使用通用的做法以及提供多种方法以适应不同语言文化的地区使用。

本地化:利用国际化中提供的方法,改变软件的行为以适应本地区语言文化的要求。

第一:可以看到,locale已经把facet组合在里面了,且所有locale对象都有一个公共的全局对象global,

目前电脑上这个全局global基本上就是"C";如果用户没有指定一个locale,那么系统默认使用这个。

第二:所有操作函数都具有const的声明,这说明locale对象一旦创建,其内容即不可更改。

第三:locate对象的,可以由下面的7个构造函数之一创建,

每个构造函数创建有不同意义的locale对象,以下就不一一说明了。

locale详细定义在C++标准里面的定义(C++标准白皮书2003第二版)可自行查阅,或在locale头文件中察看。

namespace std {

class locale {

public:

// types:

class facet;

class id;

typedef int category;

static const category // values assigned here are for expositiononly

none = 0,

collate = 0x010, ctype = 0x020,

monetary = 0x040, numeric = 0x080,

time = 0x100, messages = 0x200,

all = collate | ctype | monetary | numeric | time | messages;

// construct/copy/destroy:

locale()throw();                                                //11

locale(const locale& other)throw();                             //22

explicit locale(const char*std_name);                           //33

locale(const locale& other, const char* std_name,category);     //44

template locale(constlocale& other, Facet*f);    //55

locale(const locale& other, constlocale& one,category);        //66

~locale() throw(); // non-virtual

const locale& operator=(constlocale& other)throw();            //77

template localecombine(const locale& other)const;

//这个用于结合多个locale对象形成一个新的未命名locale对象

//比如,可以结合德国+法国的某个特性。形成一个德法混合本地对象。

// locale operations:

basic_string name()const;

bool operator==(const locale& other) const;

bool operator!=(const locale& other) const;

template

bool operator()(constbasic_string&s1,

constbasic_string&s2) const;

// global locale objects:

static locale global(const locale&);

static const locale& classic();

};

}

facet 有很多种:

ctype(字符分类),

codecvt(编码转换),

collate(校对),

numputct(数字标点信息),

num_get(数字解析),

num_put(数字格式化),

moneyputct(货币标点信息),

money_get(货币解析),

money_put(货币格式化),

time_get(时间解析),

time_put(时间格式化)

由此我们可以实现自己的facet就可以自由定制编码的输入输出,从而实现本地化的目标。

我们现在想建立一个Unicode的文本文件,在C++中需要自己实现一个facet,

否则就只有使用C函数_wfopen...等等。

如何实现:既实现 codecvt 转换的Unicode的特化的facet版本。

关于facet

facet

ctype(字符分类有:)alpha,digit,crtl,lower,print,punc(标点),space,upper,xdigit(16进制的0-F),alnum,graph等。

成员函数is():判定是否所属分类;为方便使用,std重新封装,变成isspace,isalpha..等形式。

std::tolower,std::toupper也是调用的ctype的成员函数tolower,toupper实现的,可找到老家了。

ctype另两个有用的成员函数是:narrow,widen:用于宽字符和窄字符之间的转换。

ctype还有一个串整理collate,用于字符的排序比较。这个我不太关心,我觉得让他按字符集的排列排序就可以了,呵呵。

codecvt

下面重点说一下codecvt

codecvt(编码转换),呵呵,我们要用的就是它,它就是在多字节编码和宽字符编码之间进行转换。

我们的目标就是继承他,并且实现我们自己的编码转换方案,并将它替换到一个locale对象上的facet上,

通过使用替换后的locale对象,达到实现特定编码集之间进行转换的目的。

这样我们有必要了解其每一个成员函数都是具体做什么工作的。

其定义是:

templateclass codecvt

模板参数:internT//与内部编码集相关的字符集,所谓内部编码,一般都是内存里整型变量、数组等。

模板参数:externT//与外部编码集相关的字符集,所谓外部编码,指的是外部设备。文件、管道,socket

模板参数:stateT //用于控制内外编码转换时状态的。

codecvt提供的成员函数分为两种:一种负责提供编码转换信息的,一种就是提供编码转换功能的。

负责提供编码转换信息有5个:

always_noconv() //:指出是否需要编码转换。

encoding()     //:指出是否转换与特定国家相关,外字符集/内字符集的比例是否固定,这个比例是多少?

length()       //:确定,对于给出一个外部字符集的字符,那么其内部字符的长度是多少。

MAX_length()   //:返回一个内部字符需要外部字符的最大长度。

unshift()      //: 当外部字符与与内部字符相关时,提供反向操作;

负责提供编码转换有2个:

in()          //:执行从外部编码向内部编码转换

out()         //:与in相反。

以前我们已经把对字节编码转化成了Unicode编码,输出屏幕也正确,可是一旦写入文件就会不正确

由此可以猜测到,文件流在进行写入操作时,一定是使用了系统默认提供的facet对编码进行了宽字符到多字节的编码转化。

我们现在要做的,就是使用自己定义的facet,要求文件流操作不要对编码进行转化即可。

因为我们事先已经通过mbstowcs或者MultiByteToWideChar转换好了。由此我写出了如下的facet

//这个

class UniFacet:public codecvt

{

protected:

virtualresult do_in( mbstate_t&,

const wchar_t*  , const wchar_t* , const wchar_t&  ,

wchar_t, wchar_t* , wchar_t&) const {return noconv ;}

virtual result do_out(mbstate_t& ,

const wchar_t* , const wchar_t* , const wchar_t*,

wchar_t*, wchar_t*, wchar_t& ) const {return noconv;}

virtualresult do_unshift( mbstate_t&,

wchar_t* , wchar_t* , wchar_t*)const  {return noconv ;}

virtual int do_length( mbstate_t& , const wchar_t*,

constwchar_t* , size_t ) const _THROW0() {return 1;}

virtual bool do_always_noconv() const_THROW0() {return true;}

virtual int do_max_length() const_THROW0()  {return 1;}

virtual int do_encoding() const _THROW0(){return 1;}

};

仔细看一下,这个facet作了什么转化?nothing!,对!这正是我们需要的,告诉调用者,什么都别作,原样照搬即可。

我们将通过locale 间接使用这个facet

由此我写出了如下的测试代码:验证了这个推测,不过我现在也是初窥门径,还有很多没搞清楚,总算有所得。

完整程序如下://在window下。vs2005下运行通过。

#include

#include

using namespace std;

class UniFacet:public codecvt

{

protected:

virtualresult do_in( mbstate_t&,

const wchar_t*  , const wchar_t* , const wchar_t&  ,

wchar_t, wchar_t* , wchar_t&) const {return noconv ;}

virtual result do_out(mbstate_t& ,

const wchar_t* , const wchar_t* , const wchar_t*,

wchar_t*, wchar_t*, wchar_t& ) const {return noconv;}

virtualresult do_unshift( mbstate_t&,

wchar_t* , wchar_t* , wchar_t*)const  {return noconv ;}

virtual int do_length( mbstate_t& , const wchar_t*,

constwchar_t* , size_t ) const _THROW0() {return 1;}

virtual bool do_always_noconv() const_THROW0() {return true;}

virtual int do_max_length() const_THROW0()  {return 1;}

virtual int do_encoding() const _THROW0(){return 1;}

};

int main()

{

//建一个Unicode的文本文件。

wchar_twch[100]=L"a中文Chinese与英文English混排ss",,可用MultiByteToWideChar转换,也可用mbstowcs转换";

wstringwstr=L"真是折腾人阿!!!";

wofstream UniFile;

UniFile.open("C:\UniFile.txt",ios::out|ios::binary);   //

localelocUni(locale::classic(),new UniFacet);

//这句解释一下,local::classic()是loccale的一个静态成员函数,他返回一个当前使用的

//locale对象的一个引用,我们现在通过locale的一个构造函数,重新构造一个新的locale对象

//locUni,并把其中codecvt这个facet换成我们自己定义的UniFacet.

UniFile

UniFile

UniFile.imbue(locUni);            //改变locale;

UniFile

UniFile

UniFile

UniFile

UniFile

UniFile

UniFile.close();

system("pause");

return 0;

}

//UniFile

//这句"123456"为什么也被正确转换为Unicode编码了,猜测wfostranm一定有

//且只有ASCII基本字符集里才能被正确转换。

//这个我就没有再细细追究了。

引自:http://blog.csdn.net/HewpKanXue/archive/2007/04/27/1587545.aspx

关于本地化的学习心得阅读书籍

本地化都是通过locale和facet这两个类来实现的

所有基本的国际化方法都在标准facet中提供。facet提供文化差异的服务和信息。

名次解释:国际化:尽量使用通用的做法以及提供多种方法以适应不同语言文化的地区使用。

本地化:利用国际化中提供的方法,改变软件的行为以适应本地区语言文化的要求。

第一:可以看到,locale已经把facet组合在里面了,且所有locale对象都有一个公共的全局对象global,

目前电脑上这个全局global基本上就是"C";如果用户没有指定一个locale,那么系统默认使用这个。

第二:所有操作函数都具有const的声明,这说明locale对象一旦创建,其内容即不可更改。

第三:locate对象的,可以由下面的7个构造函数之一创建,

每个构造函数创建有不同意义的locale对象,以下就不一一说明了。

locale详细定义在C++标准里面的定义(C++标准白皮书2003第二版)可自行查阅,或在locale头文件中察看。

namespace std {

class locale {

public:

// types:

class facet;

class id;

typedef int category;

static const category // values assigned here are for expositiononly

none = 0,

collate = 0x010, ctype = 0x020,

monetary = 0x040, numeric = 0x080,

time = 0x100, messages = 0x200,

all = collate | ctype | monetary | numeric | time | messages;

// construct/copy/destroy:

locale()throw();                                                //11

locale(const locale& other)throw();                             //22

explicit locale(const char*std_name);                           //33

locale(const locale& other, const char* std_name,category);     //44

template locale(constlocale& other, Facet*f);    //55

locale(const locale& other, constlocale& one,category);        //66

~locale() throw(); // non-virtual

const locale& operator=(constlocale& other)throw();            //77

template localecombine(const locale& other)const;

//这个用于结合多个locale对象形成一个新的未命名locale对象

//比如,可以结合德国+法国的某个特性。形成一个德法混合本地对象。

// locale operations:

basic_string name()const;

bool operator==(const locale& other) const;

bool operator!=(const locale& other) const;

template

bool operator()(constbasic_string&s1,

constbasic_string&s2) const;

// global locale objects:

static locale global(const locale&);

static const locale& classic();

};

}

facet 有很多种:

ctype(字符分类),

codecvt(编码转换),

collate(校对),

numputct(数字标点信息),

num_get(数字解析),

num_put(数字格式化),

moneyputct(货币标点信息),

money_get(货币解析),

money_put(货币格式化),

time_get(时间解析),

time_put(时间格式化)

由此我们可以实现自己的facet就可以自由定制编码的输入输出,从而实现本地化的目标。

我们现在想建立一个Unicode的文本文件,在C++中需要自己实现一个facet,

否则就只有使用C函数_wfopen...等等。

如何实现:既实现 codecvt 转换的Unicode的特化的facet版本。

关于facet

facet

ctype(字符分类有:)alpha,digit,crtl,lower,print,punc(标点),space,upper,xdigit(16进制的0-F),alnum,graph等。

成员函数is():判定是否所属分类;为方便使用,std重新封装,变成isspace,isalpha..等形式。

std::tolower,std::toupper也是调用的ctype的成员函数tolower,toupper实现的,可找到老家了。

ctype另两个有用的成员函数是:narrow,widen:用于宽字符和窄字符之间的转换。

ctype还有一个串整理collate,用于字符的排序比较。这个我不太关心,我觉得让他按字符集的排列排序就可以了,呵呵。

codecvt

下面重点说一下codecvt

codecvt(编码转换),呵呵,我们要用的就是它,它就是在多字节编码和宽字符编码之间进行转换。

我们的目标就是继承他,并且实现我们自己的编码转换方案,并将它替换到一个locale对象上的facet上,

通过使用替换后的locale对象,达到实现特定编码集之间进行转换的目的。

这样我们有必要了解其每一个成员函数都是具体做什么工作的。

其定义是:

templateclass codecvt

模板参数:internT//与内部编码集相关的字符集,所谓内部编码,一般都是内存里整型变量、数组等。

模板参数:externT//与外部编码集相关的字符集,所谓外部编码,指的是外部设备。文件、管道,socket

模板参数:stateT //用于控制内外编码转换时状态的。

codecvt提供的成员函数分为两种:一种负责提供编码转换信息的,一种就是提供编码转换功能的。

负责提供编码转换信息有5个:

always_noconv() //:指出是否需要编码转换。

encoding()     //:指出是否转换与特定国家相关,外字符集/内字符集的比例是否固定,这个比例是多少?

length()       //:确定,对于给出一个外部字符集的字符,那么其内部字符的长度是多少。

MAX_length()   //:返回一个内部字符需要外部字符的最大长度。

unshift()      //: 当外部字符与与内部字符相关时,提供反向操作;

负责提供编码转换有2个:

in()          //:执行从外部编码向内部编码转换

out()         //:与in相反。

以前我们已经把对字节编码转化成了Unicode编码,输出屏幕也正确,可是一旦写入文件就会不正确

由此可以猜测到,文件流在进行写入操作时,一定是使用了系统默认提供的facet对编码进行了宽字符到多字节的编码转化。

我们现在要做的,就是使用自己定义的facet,要求文件流操作不要对编码进行转化即可。

因为我们事先已经通过mbstowcs或者MultiByteToWideChar转换好了。由此我写出了如下的facet

//这个

class UniFacet:public codecvt

{

protected:

virtualresult do_in( mbstate_t&,

const wchar_t*  , const wchar_t* , const wchar_t&  ,

wchar_t, wchar_t* , wchar_t&) const {return noconv ;}

virtual result do_out(mbstate_t& ,

const wchar_t* , const wchar_t* , const wchar_t*,

wchar_t*, wchar_t*, wchar_t& ) const {return noconv;}

virtualresult do_unshift( mbstate_t&,

wchar_t* , wchar_t* , wchar_t*)const  {return noconv ;}

virtual int do_length( mbstate_t& , const wchar_t*,

constwchar_t* , size_t ) const _THROW0() {return 1;}

virtual bool do_always_noconv() const_THROW0() {return true;}

virtual int do_max_length() const_THROW0()  {return 1;}

virtual int do_encoding() const _THROW0(){return 1;}

};

仔细看一下,这个facet作了什么转化?nothing!,对!这正是我们需要的,告诉调用者,什么都别作,原样照搬即可。

我们将通过locale 间接使用这个facet

由此我写出了如下的测试代码:验证了这个推测,不过我现在也是初窥门径,还有很多没搞清楚,总算有所得。

完整程序如下://在window下。vs2005下运行通过。

#include

#include

using namespace std;

class UniFacet:public codecvt

{

protected:

virtualresult do_in( mbstate_t&,

const wchar_t*  , const wchar_t* , const wchar_t&  ,

wchar_t, wchar_t* , wchar_t&) const {return noconv ;}

virtual result do_out(mbstate_t& ,

const wchar_t* , const wchar_t* , const wchar_t*,

wchar_t*, wchar_t*, wchar_t& ) const {return noconv;}

virtualresult do_unshift( mbstate_t&,

wchar_t* , wchar_t* , wchar_t*)const  {return noconv ;}

virtual int do_length( mbstate_t& , const wchar_t*,

constwchar_t* , size_t ) const _THROW0() {return 1;}

virtual bool do_always_noconv() const_THROW0() {return true;}

virtual int do_max_length() const_THROW0()  {return 1;}

virtual int do_encoding() const _THROW0(){return 1;}

};

int main()

{

//建一个Unicode的文本文件。

wchar_twch[100]=L"a中文Chinese与英文English混排ss",,可用MultiByteToWideChar转换,也可用mbstowcs转换";

wstringwstr=L"真是折腾人阿!!!";

wofstream UniFile;

UniFile.open("C:\UniFile.txt",ios::out|ios::binary);   //

localelocUni(locale::classic(),new UniFacet);

//这句解释一下,local::classic()是loccale的一个静态成员函数,他返回一个当前使用的

//locale对象的一个引用,我们现在通过locale的一个构造函数,重新构造一个新的locale对象

//locUni,并把其中codecvt这个facet换成我们自己定义的UniFacet.

UniFile

UniFile

UniFile.imbue(locUni);            //改变locale;

UniFile

UniFile

UniFile

UniFile

UniFile

UniFile

UniFile.close();

system("pause");

return 0;

}

//UniFile

//这句"123456"为什么也被正确转换为Unicode编码了,猜测wfostranm一定有

//且只有ASCII基本字符集里才能被正确转换。

//这个我就没有再细细追究了。


相关内容

  • 捷克陨石真假鉴定
  • 本文由 在水一方捷克陨石 整理发布,允许转载. Fake Moldavite - By Mike Eggleston 假捷克陨石--迈克埃格尔斯顿 Because of limited production in the Czech Republic and increased popularity ...

  • 数据格式化
  • java.text 包允许通过与特定语言无关的方式格式化文本消息.日期和数值. 1.    数据格式化相关类介绍 类    功能介绍 java.util.*    Locale    表示一个语言和区域的特定组合 ResourceBundle    ListResourceBundle Proper ...

  • 英语故事-你知道时间的故事吗-
  • 英语故事:你知道时间的故事吗? "Do you know the time?" " 你知道时间吗?" Time is a very complex thing. We're surrounded by it, yet all too often we feel ...

  • 大连理工版实用英语(工程管理类)第四单元翻译
  • The Emerging Role of Management in Civil Engineering 管理土木工程新兴的作用 1.During the past two decades,many civil engineering firms have grown substantially i ...

  • SciTE研究 - 中文小组
  • http://groups.google.com/group/scite-cn SciTE研究 - 中文小组 2008-08-28 10:24 初学者入门教程 360pskdocImg_0_xyz 简单介绍 360pskdocImg_1_xyzSciTE(Scintilla Text Editor) ...

  • 肯德基品牌中国本土化营销策略的研究
  • 摘 要 本论文以当前跨国企业越来越重视海外市场为背景,抓住这个经济热点,以肯德基品牌做为一个切入点来研究跨国企业的本土化营销策略. 此次论文研究意义在于 ,通过对肯德基这种已经十分成熟的跨国企业的本土化营销策略的研究以期给我们正处于成长阶段的中国餐饮业带来一些好的借鉴.本文以市场营销的中的" ...

  • 毕业论文:肯德基中国地区本土化发展战略研究
  • 2010届本科生毕业设计(论文) 题目: 肯德基中国地区本土化发展战略的研究 学 生 姓 名: 院 系: 经济学院 专业.班级 : 国际经济与贸易 学 号 : 指 导 教 师: 完 成 日 期: 2010年06月 二 0 一 0 年 六 月 摘 要 跨国公司为实现经营全球化,势必面对不同的社会文化. ...

  • 联合国人类发展报告中国部分(2007-2008)中英文对照词汇表
  • Public's perceptions of employment services (基本公共服务均等化政策目标的)核心 The thrust of- (民间)社会组织 Civil society organizations "吃饭"财政(财政收入用于发工资) the rev ...

  • 美国文学史期末考试资料
  • 一. 殖民时期的美国: Colonial America 17c早--18c末 1. 从英国探险者和殖民者在新大陆的作品开始,描述他们在新大陆真实而精力充沛的冒险. 2. 另一类为清教作品 Philip Freneau 菲利普·费瑞诺:第一位美国抒情诗人兼记者 "Father of Ame ...