`
hacker_zxf
  • 浏览: 148286 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

[转]关于unicode,mbcs,utf8,charset,encoding等相关概念的说明

 
阅读更多
转自:http://www.bloggern.com/2945.html

好像第一次遇到跟字符集有关的问题大概应该是在7年前,第一次写java,总是会出现编码转换的问题,动不动就乱码,基本上,本着实用主义的态度,以盲人摸象的手法,总算是能够解决问题的。这些年来,不停的会遇到编码方面的问题,随着每一次解决问题,都感觉多揭开了一点笼罩在这一堆乱七八糟的东西上面的迷雾,然而,直到去年年中,我仍然没有完全搞明白这堆乱七八糟的名词和概念之间,究竟是怎样的关系。

去年年中开始的项目,需要用c++来处理文档,不可避免的遇到了编码转换的问题,在用c++处理的时候,我不得不仔细的探究在不同的编码转换的时候究竟发生了什么事情,终于,总算是搞明白了这些东西。下面,我会试着解释一下这些概念本身以及他们之间的关系,部分解释来自维基百科或者msdn,版权不属于我。

ANSI/ASCII : 由美国国家标准委员会指定的是基于拉丁字母的一套电脑编码系统。它主要用于显示现代英语和其他西欧语言。它是现今最通用的单字节编码系统,并等同于国际标准ISO 646。(from wiki)

MBCS : 多字节字符集,是一种替代 Unicode 以支持无法用单字节表示的字符集(如日文和中文)的方法。为国际市场编程时应考虑使用 Unicode 或 MBCS,或使程序能够通过更改开关来生成支持两种字符集之一的程序。最常见的 MBCS 实现是双字节字符集 (DBCS)。一般来说,Visual C++(尤其是 MFC)完全支持 DBCS。(from msdn)

UNICODE : 是业界的一种标准,它可以使电脑得以呈现世界上数十种的文字系统。Unicode 是基于通用字元集(Universal Character Set)的标准来发展,并且同时也以书本的形式(The Unicode Standard,目前第五版由Addison-Wesley Professional出版,ISBN-10: 0321480910)对外发表。Unicode 包含了超过十万个字元(在西元 2005 年, Unicode 的第十万个字元被采纳且认可成为标准之一)、一组可用以作为视觉参考的代码图表、一套编码方法与一组标准字元编码、一套包含了上标字、下标字等字元特性的列举等。(from wiki)

UTF-8 : 英文全称为8-bit UCS/Unicode Transformation Format,是针对Unicode 的一种可变长度字元编码。从名称可以看出,UTF-8是专为UCS/Unicode设计的传输格式。它可以用来表示 Unicode 标准中的任何字元,而且其编码串流中的第一个位元组仍与 ASCII 兼容,令原来处理 ASCII 字符的软件无需或只作少量改动后,便可继续使用。因此,它逐渐成为电子邮件、网页及其他储存或传送文字的应用中,优先采用的编码。(from wiki)

基本的名词解释完了,现在来仔细的解释一下Charset/Encoding(字符集/编码)。Charset很容易和Encoding搞混,也是刚开始接触字符编码问题是最容易被晕掉的概念。字符集的概念,实际上,包含两个方面,一个,是字符的集合,即所谓的Charset,一个是编码方案,也就是所谓的Encoding。所谓字符的集合,意即一个字符集,定义了它所包含的所有符号,这实际上正是字符集名字的真正含义。也就是说,狭义上的字符集,并不包含编码方案,它仅仅是定义了哪些符号属于这个字符集。但是,通常来说,一个字符集并不仅仅定义字符集合,同时,它还为每个符号定义一个二进制编码,所以,当我们提到GB2312的时候,我们并不仅仅是指GB2312字符集,同时,也指明了编码方案是GB2312,即Charset= GB2312,Encoding=GB2312,这说明,我们的文档中不包含GB2312以外的字符,而它们的二进制编码采用GB2312规定的编码方式。简单的情况的确如此,字符集等于编码,编码等于字符集。

但是,通常把我们搞晕的,正是一个例外,Unicode。Unicode字符集本身定义的编码方案通常称为UCS-2,或者一个更通用的名字, UTF-16。然而,由于UTF-16不能和现行的基于ascii的编码方案兼容,比较重点的问题在于0x0,在基于ascii的编码方案中,一个8位的 0x0总是表示一个字符串的结束的,而UTF-16则不然,它的一个字符,完全有可能在高8位或者低8位上等于0x0,这会导致很多应用程序错误,尤其是在网络传输协议当中可能导致大量的字符串错误截断。于是,有了UTF-8,UTF-8提供了一个跟ascii兼容的unicode字符集编码方案。网络上常见的说法说UTF-8是1到3位变长编码,这是错误的,UTF-8是1到6位变长编码,3位的说法来源于大多数常用汉字被包括在3位编码的范畴以内,而另外,从现行的Unicode规范来讲,UTF-8实际上是1到4位的编码,因为再加上两位编码所扩展的范围现在Unicode还没有定义任何字符。 UTF-8的编码方案首先保证跟127个标准ascii字符兼容,也就是说,在UTF-8方案下,Unicode的0x000000–0x00007F范围的字符被表达为0x0-0x7F的一个字节的二进制编码。其次,UTF-8保证,所有0x7F以上的字符,在被转译成多字节字符时,每个字节的最高位一定为1,这实际上也是大多数MBCS方案的基本原则,否则应用程序没法识别多字节字符的字节组合方式或者出现错误的0x0。问题在于,一般的DBCS双字节方案可以简单的根据高位是否为1而判定单字节还是双字节,而UTF-8是变长的,应用程序需要知道如何组合连续的字节数据,按照UTF-8的规定,除了最高的一个字节外,其余的所有字节均以10开头,而最高字节的开头,110表示连续2位,1110表示连续3位,11110表示连续4位。(一个具体字符的UTF-8编码值根据一个简单的对应算法从UTF-16得到,这里就不详细讲述,请自行google)。因此,我们必须明确一个概念,UTF-8是 unicode字符集的一个编码方案,当我们在说到UTF-8字符和Unicode字符的时候,在某些情况下,它们在逻辑上是等价的,但是,他们并不是同一个东西,因为Unicode字符在二进制上还有一个选择就是原生的UTF-16编码。

总结一下,Unicode字符集规定的标准编码方案是UCS-2(UTF-16),用两个字节表示一个Unicode字符,而事实上,UCS-4 (UTF-32)也已经被提出了,用4个字节表示一个Unicode字符,然后,一个常用的Unicode编码方案—UTF-8,它用1到4(6)位的变长字节来表示一个Unicode字符,并可以从一个简单的转换算法从UTF-16直接得到。这三个编码方案(Encoding)都对应于Unicode字符集(Charset)。

然后,需要解释一下Codepage-代码页,codepage实际上是一张表,通常的codepage是一个从unicode到其他mbcs的转换索引表,比如windows上常用的MS936代码页,实际上就是GB2312到unicode的转换表,我们知道,windows是完全基于 unicode的,MS的应用程序也大多是基于unicode开发的,他们对GB2312的支持,正是来源于codpage932,通过cp932的转换,应用程序可以在unicode和gb2312之间来回转换。需要多一句嘴的是关于日文编码,IBM和微软都提供了几个工业上常用的日文编码的代码页,比如对于shift-jis,IBM的代码页是CCSID943,这也是java在转换时使用的代码页,而MS的代码页是MS936,他们两者都是针对 shift-jis的代码页,算是两个并行的工业标准,在某些字符上转换结果并不一致,这可能会导致应用程序错误,比如我遇到的典型问题是通过java程序将shift-jis数据转换为unicode后传输给VC编写的程序再转换为shift-jis,由于在两次转换中使用了不兼容的代码页,导致数据错误。这并没有什么特别的解决办法,只能是查找特殊字符列表作特殊处理。

另外一个问题,就是所谓的基于unicode的应用程序,在应用程序内部字符串究竟以什么形式表达,一般来说,是以UCS-2也就是UTF-16 的二进制形式来表达的,UTF-8一般只是作为数据传输格式和文档保存格式。具体一点,对于java代码,javac编译程序在你没有指定源文件编码的情况下,总是将其认为是本地缺省编码,比如在简体中文windows上会被认识为GB2312,而在日文windows上会被识别为shift-jis,然后实际上,在编译的时候,gb或者jis字符都会被转换成对应的UCS-2二进制值。而对于C++程序,当你简单的用 ”中” 这样的引号引用的形式的时候,编译器会简单的将其识别为本地编码并且在编译后的二进制代码中被表达为本地编码的二进制值(我不知道c++编译器能否指定源文件编码。。。我不太熟悉c++),但是,如果你用 L”中” 这样的标准c++的unicode字符定义方式来定义字符时,将会发生和javac编译程序一样的事情,编译程序会主动的将字符正确的以本地编码识别并转换成UCS-2值保存为编译后的二进制代码。C++程序中,如果以L宏定义字符串,可以在程序中直接得到Unicode值,即UTF-16编码值,但在 java中,实际上我们并不能直接得到字符串的二进制值,不过可以通过String的getbytes方法指定UTF-16编码得到。至于各种编码之间的转换,这里就不赘述了。

最后,解释一下关于font的问题,其实,很多时候我们遇到的乱码并没有出现编码转换错误,只是由于应用程序指定的字体没有包含对应的字符图像而已,这种情况,通常我们可以看到有部分字符是可以正常显示的。Font文件实际上也是一个索引文件,一个encoding索引加上位图。现在的字体文件通常包含两个编码索引,一个unicode,一个该字体对应语言的常用编码,应用程序在显示字符的时候,通过查找对应的索引而得到字符的位图。
分享到:
评论

相关推荐

    utf8 宽字节 mbcs 随意转换

    utf8 宽字节 mbcs 随意转换 vtString WStringToUTF8(const wchar_t* wstring); vtString2 UTF8ToWString(const char *string_utf8); vtString WStringToMBCS(const wchar_t* wstring); vtString2 MBCSToWString...

    Unicode MBCS字符转换程序.rar

    本项目"Unicode MBCS字符转换程序.rar"专注于解决字符编码的转换问题,包括Unicode16le、Unicode16be、utf-8以及MBCS(多字节字符集)之间的相互转换。下面我们将深入探讨这些编码方式及其转换的原理与实践。 首先...

    C++各种编码转换 Unicode UTF8

    根据提供的文件信息,本文将详细解释C++中几种常见的字符编码转换方法,特别是涉及Unicode与UTF-8之间的转换。在实际开发过程中,由于不同的系统、软件可能会采用不同的字符编码方式来存储文本数据,因此实现不同...

    多字节与UTF-8、Unicode之间的转换

    本篇文章主要探讨的是多字节(MBCS)编码与UTF-8、Unicode编码之间的转换方法,并深入分析了给定代码片段中的六个函数实现细节。 #### 一、基础知识概述 1. **多字节字符集(MBCS)**:多字节字符集是指非固定长度...

    升级VC6源码mbcs转unicode

    本话题主要涉及的是将一个使用Visual C++ 6(VC6)开发的源码项目升级到更高版本,如VC2002,并且处理MBCS(多字节字符集)到UNICODE(宽字符集)的转换。以下是对这个过程的详细解释: 1. **VC6与VC2002的差异**:...

    MBCS编码和UNICODE编码的相互转换.docx

    在编程领域,字符编码是处理...总的来说,MBCS和UNICODE编码之间的转换涉及了类型转换、字符串函数的替换、宏定义的使用以及API调用等多个方面。正确理解和应用这些转换规则,能够确保程序在不同编码环境中正常工作。

    MBCS编码和UNICODE编码的相互转换.pdf

    在编程领域,字符编码是处理文本数据的关键环节。MBCS(Multiple Byte Character...然而,随着开发工具的更新,如VC7、VC8等更现代的编译器,它们通常默认支持Unicode,并提供了更好的编码兼容性,简化了开发者的工作。

    Utf8ToCString

    1. **UTF-8转中文(ANSI/MBCS)**: 这通常涉及到`MultiByteToWideChar`和`WideCharToMultiByte`这两个Windows API函数。`MultiByteToWideChar`将多字节字符串(如UTF-8)转换为宽字符字符串(UTF-16,Windows内部...

    最新unicode点阵字库生成工具(fontmaker)

    增加了一个字符串mbcs2unicode(内码转统一码)的功能。 (支持转:U16-LE, U16-BE, UTF8) V1.03 (20110705) 1. 修改了 Example 中点阵字库解析源码,更加便于移植。(基本做到只需修改font_file.c 即可) 2. 修改...

    易语言Ansi与Unicode转换源码.7z

    Unicode包含了大量的字符集,如UTF-8、UTF-16等,能够支持多种语言的显示,解决了Ansi编码的局限性。其中,UTF-8是最常见的一种Unicode编码,它用1到4个字节表示一个字符,兼容ASCII编码。 易语言中的Ansi与Unicode...

    UTF8.zip_Change

    标题“UTF8.zip_Change”和描述“Charset Change Module UTF-8 Code: Visual Basic 6.0”揭示了这个压缩包文件与字符编码转换有关,特别是涉及到从其他字符集转换到UTF-8编码的模块。这个模块是用Visual Basic 6.0...

    Unicode与ANSI字符串之间的转换

    Unicode 最常见的实现形式包括 UTF-8、UTF-16 和 UTF-32。其中,UTF-16 是 Windows 平台上广泛采用的 Unicode 编码形式,它使用 16 位(两个字节)来存储大部分常用字符,对于非常用字符则使用四个字节来存储。 ###...

    vs2008-Unicode字符集下CString与char_互转换

    在VS2008中,默认的字符集形式是Unicode,但在VC6.0等工程中,默认的字符集形式是多字节字符集(MBCS:Multi-Byte Character Set),这样导致在VC6.0中非常简单实用的各类字符操作和函数在VS2008环境下运行时会报...

    VCB API UCS 与UTF编码转换

    "VCB API UCS 与UTF编码转换"是一个针对VB(Visual Basic)编程环境的实用技术,它涉及到字符集的互换,包括UCS(Unicode Character Set)和UTF(Unicode Transformation Format)之间的转换。本文将深入探讨这两个...

    Unicode编码源代码

    - **UTF-8、UTF-16和UTF-32**: UTF-8是最常用的Unicode变体,它以可变长度的方式编码字符,从1到4个字节不等。UTF-16则通常用2个字节表示字符,对于UCS-2范围内的字符与UCS-2相同,而超出的字符使用4个字节。UTF-32...

    VS2008在Unicode环境下将Unicode文本转为ANSI文本

    相比之下,ANSI(通常指的是Windows API中的“MBCS”,即多字节字符集)是基于特定区域设置的编码,它主要适用于英语和其他少数欧洲语言,使用8位编码来表示字符。 在VS2008中进行Unicode到ANSI的转换,通常涉及...

    [原创]Unicode2ANSI

    最常见的Unicode实现是UTF-8,它使用1至4个字节表示一个字符,使得所有语言都能被包容。 在标题提到的"Unicode2ANSI"场景中,我们面临的是将Unicode编码的文本转换为ANSI编码的过程。这种转换可能在某些情况下是...

    Unicode知识介绍

    ### Unicode知识介绍 ...理解Unicode及其相关概念对于从事软件开发、网页设计或任何涉及文本处理的领域都是至关重要的。随着全球化的不断推进,Unicode的重要性只会持续增加,成为连接世界语言的桥梁。

    unicode编码文档

    Unicode编码有多种实现方式,其中最常见的有UTF-8、UTF-16和UTF-32。UTF-8是最广泛使用的Unicode变体,它使用1到4个字节来表示一个字符,根据字符的不同,字节数量会有所变化。UTF-8的优势在于,它兼容ASCII编码,...

    unicode 转GB

    常用的Unicode编码形式包括UTF-8、UTF-16等。 - **GB编码**:是中国国家标准汉字编码方案的一种,主要包括GB2312、GBK、GB18030等。GB2312是最基本的标准,收录了大约7000个常用汉字及符号;GBK在其基础上进行了扩展...

Global site tag (gtag.js) - Google Analytics