zoukankan      html  css  js  c++  java
  • 跨平台程序的UNICODE字符串处理方法。

    在windows下面编程,我们通常都知道unicode这个概念,如果一个程序是unicode的,那么他将调用

    unicode的api。这个时候,所有传递给api的字符串参数都要是unicode的.如果使用C的风格,是很简单的

    ,字符串全部由char* str 转变成TCHAR* str,使用的crt函数(其实也是api)时调用_tcslen类的函数族就

    可以了。

    在讨论其它问题前要先明确一个概念:unicode 与 utf-8编码,utf-16编码是两个不同类别的术语。

    unicode对一个字符提供了一个唯一的编码(参看下面的资料,关于UCS-2与UCS-4)
    假设"中"这个字符的编码是0x34 0x34(我乱写的),utf-8对其编码,得到的是 0xE3 0x90 0xB6 需要3byte

    的空间进行存储。不同的unicode码经过utf-8编码后会得到变长的结果.比如说'a'经过utf-8编码后得到

    的是和ascii码相同,只占1个byte.对unicode使用不同的方法编码,可以有效的节约存储空间(如果选择了

    错误的编码,会浪费空间).

    中的unicode(UCS-2)值和编码后的结果
    unicode                            utf-8          
    00110100 00110100      11100011  10010000 10110110
    a的unicode值和编码后的结果
    unicode                            utf-8
    00000000 01100001      01100001

    这里得出的结论是utf-8,utf-16编码是在存储字符串信息前的一个选择,而不是处理字符串的选择.


    OK,问题回到字符串编程上来。第一个问题,就是要选择内存中的字符串格式,包括自己所有需要传递字

    符串参数的函数的参数定义。我们这里有3个选择,char*(ASCII string),unsigned short*(UCS2

    string,windows下的unicode),unsigned long*(UCS4 string,真正的unicode支持)。windows下的api是不

    支持UCS4的,所以在windows平台下最好只做前2个的选择。类似于windows的TCHAR定义,我们可以做这样

    的定义
    #ifdef _UCS2
    #define TCHAR unsigned short
    #else
    #ifdef _UCS4
    #define TCHAR unsigned long
    #else
    #define TCHAR char
    #endif
    #endif
    然后有一个问题,如果在程序中需要使用一个预定义的字符串,比如说
    TCHAR* str = "中国";
    那么,str指向的常量字符串的编码是ACSII string,还是UCS2 unicode string,还是UCS4 unicode

    string,是取决于编译器的。这样就容易造成许多不易发现的错误。这里要推荐一个string table的概念

    ,用如下代码替换。
    const TCHAR* str = StringTable::LoadStr(ID_HOMELOAD_NAME);
    StringTable类解析一个指定编码的本地字符串表XML文件(可以用各种编码存储),这个文件可以使用自定

    义的工具或则是各种XML编辑工具来生成。使用StringTable::SetOutPutType(enum MemStrType)来使之在

    LoadStr的时候转成各种字符串编码。当然,这个类中定义了一系列的编码转换函数,比如说

    UTF8TOASCII,UTF8TOUCS2,UTF8TOUCS4,UCS4TOUCS2,UCS4TOASCII,UCS4TOXXX,StringTalbe内部使用UCS4作

    为读取后的字符串存储格式,然后再根据StringTable::SetOutPutType指定的输出类型生成相应编码的

    Table.这样做的好处就是把这个编码的问题重视化,即时出现编码不一致的错误,也能立刻修正。

    在linux下,系统对UCS4的支持比较好,#include<wchar.h>,里面的函数的接口都是ucs4 string.所以如果写跨平台程序,肯定是要用ucs2的(UCS4windows不支持,而且可以节约内存,但是你的程序就不是真正的UNICODE3.1 Support了,而且也不能支持国家标准GB18030).然后再调用linux的相关函数时,转化为UCS4.参考文章http://www0.ccidnet.com/tech/os/2001/07/31/58_2811.html。我懒得写了。


     -----------------------------------
    p.s 我摘得一些相关术语的定义
    Unicode 的定义
    Unicode 通常用作涉及双字节字符编码方案的通用术语。Unicode CCS 3.1 的官方称谓是 ISO10646-1 通

    用多八字节编码字符集(Universal Multiple Octet Coded Character Set,UCS)。Unicode 3.1 版本

    添加了 44,946 个新的编码字符。算上 Unicode 3.0 版本已经存在的 49,194 个字符,共计 94,140 个

    Unicode 编码字符集利用了一个由 128 个三维的组构成的四维编码空间。其中每个组包含 256 个二维平

    面。每个平面由 256 个一维的行组成,并且每个行有 256 个单元。每个单元在这个编码空间内对一个字

    符编码,或者被声明为未经使用。这种编码概念被称为 UCS-4;四个八位元用来表示指定组、平面、行和

    单元的每个字符。

    第一个平面(第 00 组的第 00 平面)是基本多语言平面(Basic Multilingual Plane,BMP)。BMP 按

    字母、音节、表意符号和各种符号及数字定义了常规使用的字符。后续的平面用于附加字符或其它还没有

    发明的编码实体。我们需要这完整的范围去处理世界上的所有语言;特别是拥有将近 64,000 个字符的一

    些东亚语言。

    BMP 被用作双字节的编码字符集,这种编码字符集确定为 ISO 10646 UCS-2 格式。ISO 10646 UCS-2 就

    是指 Unicode(并且两者相同)。BMP,像所有 UCS 平面那样,包含了 256 行,其中每行包含 256 个单

    元,字符仅仅按照 BMP 中的行和单元的八位元在单元中被编码。 这就允许 16 位编码字符能够被用来书

    写大多数商业上最重要的语言。UCS-2 不需要代码页切换、代码扩展或代码状态。UCS-2 是一种将

    Unicode 结合到软件中的简单方法,但它只限于支持 Unicode BMP。

    若要用 8 位字节表示一个多于 2^8 =256 个字符的字符编码系统(character coding system,CCS),

    就需要一种字符编码方案(character-encoding scheme,CES)。


    UTF-8
    UTF-8 转换格式正逐步成为一种占主导地位的交换国际文本信息的方法,因为它可以支持世界上所有的语

    言,而且它还与 ASCII 兼容。UTF-8 使用变长编码。从 0 到 0x7f(127)的字符把自身编码成单字节,

    而将值更大的字符编码成 2 到 6 个字节。

    表 1. UTF-8 编码
    0x00000000 - 0x0000007F:  0 xxxxxxx 
    0x00000080 - 0x000007FF:  110 xxxxx10 xxxxxx 
    0x00000800 - 0x0000FFFF:  1110 xxxx10 xxxxxx10 xxxxxx 
    0x00010000 - 0x001FFFFF:  11110 xxx10 xxxxxx10 xxxxxx 10 xxxxxx 
    0x00200000 - 0x03FFFFFF:  111110 xx10 xxxxxx10 xxxxxx10 xxxxxx 10 xxxxxx 
    0x04000000 - 0x7FFFFFFF:  1111110 x10 xxxxxx10 xxxxxx10 xxxxxx 10 xxxxxx10 xxxxxx 

  • 相关阅读:
    VS2015 调试中断点突然失效的解决办法、VS调试时关闭调试让浏览器继续保留页面
    Postman调用WebService,包括头验证部分
    C# 正则表达式大全
    Webservice超时问题
    C# DateTime的 ParseExact和 TryParseExact 使用说明
    4、QT分析之调试跟踪系统
    5、QT分析之网络编程
    QIODevice (Qt中所有 I/O devices 的基类,QFile,QBuffer,QTcpSocket等)
    Qt 菜鸟的坑 QAbstractSocket::isValid()
    qt之QAbstractSocket
  • 原文地址:https://www.cnblogs.com/waterflier/p/272996.html
Copyright © 2011-2022 走看看