`
casec12
  • 浏览: 46661 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

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

阅读更多

好像第一次遇到跟字符集有关的问题大概应该是在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的差异**:...

    Utf8ToCString

    UTF-8是一种广泛使用的Unicode编码方式,它可以表示Unicode字符集中的所有字符。而在Windows CE(WCE)平台上,以及Visual Studio 2005(VS2005)这样的开发环境中,与UTF-8进行交互可能会有一些特定的挑战。"Utf8...

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

    增加输出编码格式 (mbcs, utf16-lb, utf8)设置 2. 增加数组格式输出。 Image Manager(图像管理) 1. 该页为新增功能,支持图片图像的数据转换。主要应用在做产品logo图片方面。 V1.04 (20110716) 1. 增加了一...

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

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

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

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

    Unicode编码源代码

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

    Unicode知识介绍

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

    UTF8.zip_Change

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

    unicode编码文档

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

    在C和C++中使用Unicode

    - 随着Unicode标准的发展,出现了多种不同的编码方式,如**UTF-16**(默认的Unicode编码)、**UTF-8**以及**UTF-32**等。每种编码方式都有其特定的应用场景和优势。例如,UTF-8因其良好的向后兼容性和高效性而成为...

    给肥胖的VS2005去掉Unicode

    常见的Unicode编码有UTF-8、UTF-16等。UTF-8是变长编码,兼容ASCII,且能高效地表示非英文字符;UTF-16则固定使用2或4个字节表示一个字符,适用于需要固定长度编码的应用场景。 ### 如何在VS2005中去除Unicode 若...

    VC++的Unicode编程

    8. **兼容性问题**: 当Unicode程序与非Unicode程序交互时,可能需要进行字符编码转换,例如,读取ANSI格式的配置文件或使用不支持Unicode的第三方库。 9. **调试和输出**: 在调试时,注意宽字符和窄字符的差异,...

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

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

    Unicode与ANSI字符串之间的转换

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

    Windows_Unicode_.rar_unicode_visual c

    以下是对"Windows_Unicode_.rar_unicode_visual c"主题的详细说明: 1. **Unicode基础**:Unicode是一个字符集,由Unicode联盟维护,旨在为全球所有语言提供一个统一的字符编码。它使用16位或32位的数字来表示每个...

    GuiLib1.5 unicode vs.net 2005

    Unicode有两种主要实现方式:UTF-8和UTF-16。UTF-8是目前最广泛使用的Unicode编码,因为它兼容ASCII并且在大多数情况下节省存储空间。 另一方面,MBCS(Multi-Byte Character Set)是为那些使用非ASCII字符集的东亚...

Global site tag (gtag.js) - Google Analytics