【翻译文章】如何升级基于STL的应用来支持Unicode

翻译 2005年05月26日 17:32:00

来源: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

APP不通过AppStore下载,APP应用内完成升级(不需要重新上传、审核)---他人文章链接,自己留着

APP不通过AppStore下载,APP应用内完成升级(不需要重新上传、审核),应用内下载...

升级VC6源码mbcs转unicode

  • 2015年08月07日 17:24
  • 137KB
  • 下载

Windows Mobile技术文章翻译系列(1)—为Windows Mobile设备创建位置感知的应用程序

为你的应用程序添加位置感知并在当前位置呼叫Web服务,不仅为在线商务应用也为其他各种各样的消费者应用程序增加了许多潜在价值。你可以根据本文介绍的技术通过GPS检索或蜂窝站点检索获取当前位置从而开发具备...

(转)标准模板库(STL)的 std::string 与Unicode的使用

是的,一旦知道 TCHAR 和_T 是如何工作的,那么这个问题很简单。基本思想是 TCHAR 要么是char,要么是 wchar_t,这取决于 _UNICODE 的值: // abridged f...
  • gxj1680
  • gxj1680
  • 2011年05月05日 17:40
  • 689

微软应用架构指南系列文章翻译

起因: 最近忙于俗事,再加上懒(这才是重点),博客很久都没有更新了,对写点什么也毫无头绪,无意中上网看到MSDN上一整套讲解微软技术架构的文章,挑着读了几篇,感觉甚是不错,自古独乐乐不如众乐乐...

(文章来自cocochina.com)iOS应用支持IPV6,就那点事儿

一、IPV6-Only支持是啥? 首先IPV6,是对IPV4地址空间的扩充。目前当我们用iOS设备连接上Wifi、4G、3G等网络时,设备被分配的地址均是IPV4地址,但是随着运营商和企业逐渐部...

STL使用Unicode编码——tstring

是的,一旦知道 TCHAR 和_T 是如何工作的,那么这个问题很简单。基本思想是 TCHAR 要么是char,要么是 wchar_t,这取决于 _UNICODE 的值:        // ab...

关于UTF-8,ANSI,以及Unicode的一些文章

缘起      我从上大学开始使用windows系统二年半后换成Ubuntu,以前在windows下写得代码文件和相应的txt文本中很多都是保存为Windows下ANSI码格式的,而这些文件一到Ub...

转发一篇关于ANSI,Unicode,UTF-8编码的文章,我认为是最容易动的,最详细的

很久很久以前,有一群人,他们决定用8个可以开合的晶体管来组合成不同的状态,以表示世界上的万物。他们看到8个开关状态是好的,于是他们把这称为"字节"。再后来,他们又做了一些可以处理这些字节的机器,机器开...

C++ STL IO流与Unicode协同工作

凡用到文件读写,输入输出,就得和编码、Unicode 打交道。这系列实验来测试一下 C++ STL 的 IO流 对 ANSI 编码、Unicode 编码的支持特性,看能否找到一个自动识别编码,自动转码...
  • jiht594
  • jiht594
  • 2011年10月04日 23:39
  • 488
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:【翻译文章】如何升级基于STL的应用来支持Unicode
举报原因:
原因补充:

(最多只允许输入30个字)