【翻译文章】如何升级基于STL的应用来支持Unicode
2005-05-26 17:32
736 查看
来源:http://dozb.blogchina.com/1655050.html
翻译作者:dozb,Nicole
原作者:Taka Muraoka
原出处:http://www.codeproject.com/vcpp/stl/upgradingstlappstounicode.asp
天啊,我是多么地错误:((
因此,我写这篇文章是为了治疗两周工作之痛,并且希望解除其他人的痛苦,这痛苦是我已经经受的。唉...
你将像这样用它们:
到底怎么啦?
这渊源是标准C++的规定,wide流当写到 file。必须转换double-byte 到single-byte 。如上例,宽字符串L"ABC"(有6个字节长),当写到文件前,被转换成窄字符串(3字节)。更坏的情况,如何转换由库的实现来决定的( implementation-dependent)。
我不能找出一个确切的解释,为什么事情会弄成这样子。我猜测,文件被定义为考虑作为字符(single-byte)流。若允许同时写2字节的字符将无法提取。不管对还是错,这都导致严重的问题。例如,你不能写二进制数据到wofstream,因为这个类试图在输出前先窄字符化它。
这对我是明显的问题,因为我有大量的函数像这样写:
解决方案:写一个新的继承自codecvt的类,用来转换wchar_ts 到 wchar_ts(什么也不做),绑定到wofstream 对象中。当wofstream 试图转换它所输出的数据时,它将调用我们新的codecvt 对象,实际上什么也不做,不改变地写输出数据。
在google groups浏览找一些P. J. Plauger写的代码 code (是MSVC环境中STL库的作者),
用来解决用 Stlport 4.5.3 的编译问题。 这是最后敲定的版本:
http://dozb.blogchina.com/1655050.html
翻译作者:dozb,Nicole
原作者:Taka Muraoka
原出处:http://www.codeproject.com/vcpp/stl/upgradingstlappstounicode.asp
介绍
我最近升级一个想当大的程序,目的是用Unicode代替single-byte 字符。除了少数遗留下来的模块,我忠实地使用t-functions并且用_T()宏包裹我的字符串和字符常量,众所周知这能安全的转换成Unicode,我要做的事情是定义UNICODE 和 _UNICODE,我祈祷所有事情将如我所愿的工作。天啊,我是多么地错误:((
因此,我写这篇文章是为了治疗两周工作之痛,并且希望解除其他人的痛苦,这痛苦是我已经经受的。唉...
基础
理论上,写出用single- 或 double-字节字符能被编译的代码是直接的。我曾经想在这里写一节,但是Chris Maunder 已经写了 done it. 他描述的技术是广为人知的,因此对理解这篇文章的内容非常有帮助。Wide 文件 I/O
这里是stream类的wide版本,它容易地定义t-风格的宏去管理他们:你将像这样用它们:
tofstream testFile( "test.txt" ) ; testFile << _T("ABC") ;现在,你期待的结果是,当用single-byte 字符编译的时候,执行代码将生成3字节的文件,当用double-byte 字符编译的时候,执行代码将生成6字节的文件。但是你错了,都是3字节的文件。
到底怎么啦?
这渊源是标准C++的规定,wide流当写到 file。必须转换double-byte 到single-byte 。如上例,宽字符串L"ABC"(有6个字节长),当写到文件前,被转换成窄字符串(3字节)。更坏的情况,如何转换由库的实现来决定的( implementation-dependent)。
我不能找出一个确切的解释,为什么事情会弄成这样子。我猜测,文件被定义为考虑作为字符(single-byte)流。若允许同时写2字节的字符将无法提取。不管对还是错,这都导致严重的问题。例如,你不能写二进制数据到wofstream,因为这个类试图在输出前先窄字符化它。
这对我是明显的问题,因为我有大量的函数像这样写:
void outputStuff( tostream& os ) { // output stuff to the stream os << .... }假如你传递的是tstringstream 对象将没有问题(例如,它流出宽字符),但是假如你传递的是tofstream 将得到怪异的结果(因为所有内容都被窄化了)。
Wide 文件 I/O: 解决方案
用调试器单步跟踪STL,结果发现wofstream 在写输出到文件以前,调用std::codecvt 对象来窄化输出的数据。std::codecvt对象是造成字符串从一种字符集到另一种字符集转换的原因。C++要求作为标准提供:1、转换chars 到 chars(例如,费力地什么也不做),2、转换wchar_ts 到chars。后一种就是引起我们这么多伤心事的原因。解决方案:写一个新的继承自codecvt的类,用来转换wchar_ts 到 wchar_ts(什么也不做),绑定到wofstream 对象中。当wofstream 试图转换它所输出的数据时,它将调用我们新的codecvt 对象,实际上什么也不做,不改变地写输出数据。
在google groups浏览找一些P. J. Plauger写的代码 code (是MSVC环境中STL库的作者),
用来解决用 Stlport 4.5.3 的编译问题。 这是最后敲定的版本:
#include // nb: MSVC6+Stlport can't handle "std::" // appearing in the NullCodecvtBase typedef. using std::codecvt ; typedef codecvt < wchar_t , char , mbstate_t > NullCodecvtBase ; class NullCodecvt : public NullCodecvtBase { public: typedef wchar_t _E ; typedef char _To ; typedef mbstate_t _St ; explicit NullCodecvt( size_t _R=0 ) : NullCodecvtBase(_R) { } protected: virtual result do_in( _St& _State , const _To* _F1 , const _To* _L1 , const _To*& _Mid1 , _E* F2 , _E* _L2 , _E*& _Mid2 ) const { return noconv ; } virtual result do_out( _St& _State , const _E* _F1 , const _E* _L1 , const _E*& _Mid1 , _To* F2, _E* _L2 , _To*& _Mid2 ) const { return noconv ; } virtual result do_unshift( _St& _State , _To* _F2 , _To* _L2 , _To*& _Mid2 ) const { return noconv ; } virtual int do_length( _St& _State , const _To* _F1 , const _To* _L1 , size_t _N2 ) const _THROW0() { return (_N2 < (size_t)(_L1 - _F1)) ? _N2 : _L1 - _F1 ; } virtual bool do_always_noconv() const _THROW0() { return true ; } virtual int do_max_length() const _THROW0() { return 2 ; } virtual int do_encoding() const _THROW0() { return 2 ; } } ;完整全文请看:
http://dozb.blogchina.com/1655050.html
相关文章推荐
- 如何升级基于STL的应用来支持Unicode
- 【C++ STL应用与实现】26: 如何使用std::for_each以及基于范围的for循环 (since C++11)
- 基于Django的Disqus如何支持每月80亿PV
- iOS 应用如何完全支持 IPv6-ONLY 网络?
- StevGuo系列文章翻译之Android中的输入事件如何分发
- 如何制作一款像超级玛丽兄弟一样基于平台的游戏-第二部分 (xcode,物理引擎,TMXTiledMap相关应用)
- [翻译自mos文章]weblogic 12c 支持CentOS 6/7 操作系统吗?
- 【C++ STL应用与实现】23: 如何使用std::mem_fn (since C++11)
- Android应用如何判断系统升级了?
- 基于cefsharp的浏览器应用开发(支持XP系统)
- 如何为工程添加一个Installshield不支持的语言--艾泽拉斯之海洋女神翻译
- C#如何与com交互(一篇老外的文章简单的翻译摘要)
- 【C++ STL应用与实现】13: 如何使用std::queue和std::priority_queue
- Win8.1如何升级邮件/日历/人脉应用以方便生活
- 经典技术文章翻译(2)Does WCF use or Supports IOCP?WCF是否支持或者使用了IOCP完成端口。
- 【C++ STL应用与实现】22: 函数组合之1:如何使用std::bind (since C++11)
- Win8自动更新在哪如何让应用商店推送Win8.1升级信息
- Flask at Scale (Flask如何适配到大型应用) - PyCon 2016 简明中文翻译
- Mac升级10.12,想要允许任何来源应用,如何操作?
- 微软应用架构指南系列文章翻译