`

utf-8 与unicode

阅读更多

[source]http://www.blogjava.net/stme/archive/2006/12/04/85440.html

今天在做ajax的portlet的时候用response返回数据遇到了中文乱码的问题,给我们带来了很大的麻烦。unicode、utf8、gb2312、gbk之间关系如何,互有什么渊源,对于unicode来说在将来不远的几年里, 它已经很接近于取代 ASCII 与 Latin-1 编码的位置了. 它不仅允许你处理处理事实上存在于地球上的任何语言文字, 而且提供了一个全面的数学与技术符号集, 因此可以简化科学信息交换。于是痛下决心好好研究研究研究这些编码之间的关系,以便以后能够比较轻松的解决之类的问题。经过在网上查询资料研究得出如下关于utf-8与unicode编码的心得:
    最开始美国是用Ascii来保存英文字母和一些字符(空格,标点符号等等)的。
    后来中国人们得到计算机时,已经没有可以利用的字节状态来表示汉字,况且有6000多个常用汉字需要保存呢。我们就用两个字节来表示汉字信息这样我们就可以组合出大约7000多个简体汉字了。在这些编码里,我们还把数学符号、罗马希腊的字母、日文的假名们都编进去了,连在 ASCII 里本来就有的数字、标点、字母都统统重新编了两个字节长的编码,这就是常说的"全角"字符,而原来在127号以下的那些就叫"半角"字符了。这就是GB2312。
    再后来,我们把第一个字节是大于127就固定表示这是一个汉字的开始。结果扩展之后的编码方案被称为 GBK 标准,GBK 包括了 GB2312 的所有内容,同时又增加了近20000个新的汉字(包括繁体字)和符号。后来少数民族也要用电脑了,于是我们再扩展,又加了几千个新的少数民族的字,GBK 扩成了 GB18030。
    Unicode 只是分配整数给字符的编码表,但是UNICODE 在制订时没有考虑与任何一种现有的编码方案保持兼容,这使得 GBK 与UNICODE 在汉字的内码编排上完全是不一样的,没有一种简单的算术方法可以把文本内容从UNICODE编码和另一种编码进行转换,这种转换必须通过查表来进行。UNICODE 是用两个字节来表示为一个字符,他总共可以组合出65535不同的字符,这大概已经可以覆盖世界上所有文化的符号。如果还不够也没有关系,ISO已经准备了UCS-4方案,说简单了就是四个字节来表示一个字符,这样我们就可以组合出21亿个不同的字符出来(最高位有其他用途).
    UNICODE 来到时,一起到来的还有计算机网络的兴起,UNICODE 如何在网络上传输也是一个必须考虑的问题,于是面向传输的众多 UTF(UCS Transfer Format)标准出现了,顾名思义,UTF8就是每次8个位传输数据,而UTF16就是每次16个位,只不过为了传输时的可靠性,从UNICODE到 UTF时并不是直接的对应,而是要过一些算法和规则来转换。这就是我们应用诸如tomcat的服务器其中的配置文件会有编码的设置,一般的默认设置就是utf8。
    在网络里传递信息时有一个很重要的问题,就是对于数据高低位的解读方式,一些计算机是采用低位先发送的方法,例如我们PC机采用的 x86 架构,而另一些是采用高位先发送的方式,在网络中交换数据时,为了核对双方对于高低位的认识是否是一致的,采用了一种很简便的方法,就是在文本流的开始时向对方发送一个标志符——如果之后的文本是高位在位,那就发送"FEFF",反之,则发送"FFFE"。
    讲到这里,我们再顺便说说一个很著名的奇怪现象:当你在 windows 的记事本里新建一个文件,输入"联通"两个字之后,保存,关闭,然后再次打开,你会发现这两个字已经消失了,代之的是几个乱码!呵呵......其实这是因为GB2312编码与UTF8编码产生了编码冲撞的原因。
    utf8 与 unicode 的转换标准如下:
Unicode
UTF-8

0000 - 007F
0xxxxxxx

0080 - 07FF
110xxxxx 10xxxxxx

0800 - FFFF
1110xxxx 10xxxxxx 10xxxxxx

如:中医药的 unicode 码为:\u4e2d\u533b\u836f,去掉 \u 后为:  4e2d  533b  836f
这三个字的二进制编码分别为:
0100  1110  00 10  1101
0101  0011  00 11  1011
1000  0011  01 10  1111  他们都是大于0800小于ffff,所以适用第三种模板
将他们分别编码为:
1110 0100 10 111000 10 101101   --->     e4b8ad
1110 0101 10 001100 10 111011   --->     e58cbb
1110 1000 10 001101 10 101111   --->     e88daf
e4b8ad、e58cbb、e88daf分别为:中医药 的utf8编码
    而当你新建一个文本文件时,记事本的编码默认是ANSI, 如果你在ANSI的编码输入汉字,那么他实际就是GB系列的编码方式,在这种编码下,"联通"的内码是: \u8054\u901a
c1 1100 0001
aa 1010 1010
cd 1100 1101
a8 1010 1000
注意到了吗?第一二个字节、第三四个字节的起始部分的都是"110"和"10",正好与UTF8规则里的两字节模板是一致的,于是再次打开记事本时,记事本就误认为这是一个UTF8编码的文件,让我们把第一个字节的110和第二个字节的10去掉,我们就得到了"00001 101010",再把各位对齐,补上前导的0,就得到了"0000 0000 0110 1010",不好意思,这是UNICODE的006A,也就是小写的字母"j",而之后的两字节用UTF8解码之后是0368,这个字符什么也不是。这就是只有"联通"两个字的文件没有办法在记事本里正常显示的原因。
    而如果你在"联通"之后多输入几个字,其他的字的编码不见得又恰好是110和10开始的字节,这样再次打开时,记事本就不会坚持这是一个utf8编码的文件,而会用ANSI的方式解读之,这时乱码又不出现了。
而如果你在"联通"之后多输入几个字,其他的字的编码不见得又恰好是110和10开始的字节,这样再次打开时,记事本就不会坚持这是一个utf8编码的文件,而会用ANSI的方式解读之,这时乱码又不出现了。

分享到:
评论

相关推荐

    C++ UTF-8与 Unicode互相转换.docx

    本文将详细探讨C++中如何进行UTF-8与Unicode之间的转换,以及涉及的相关知识。 首先,我们要了解UTF-8和Unicode的基本概念。Unicode是一个通用的字符集,它包含世界上几乎所有的文字和符号,每个字符都有一个唯一的...

    utf-8与unicode

    ### UTF-8与Unicode知识点详解 #### 一、引言 在计算机科学领域,字符编码是数据处理的基础之一。字符编码决定了如何将字符映射到二进制数字,从而实现字符在不同系统间的存储和传输。本文将详细介绍两种重要的...

    utf-8与unicode相互转换代码

    utf-8与unicode相互转换代码

    UNICODE与UTF-8转换

    **标题:**UNICODE与UTF-8转换 **正文:** 在计算机科学中,字符编码是用于表示文本的一种方式,特别是在计算机系统中。UNICODE和UTF-8是两种广泛使用的字符编码标准,它们各自有着独特的特性和应用场景。本文将...

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

    ### 多字节与UTF-8、Unicode之间的转换 在计算机科学领域,字符编码是将文字映射到二进制数据的一种方式。不同的字符编码方案适用于不同的应用场景。本篇文章主要探讨的是多字节(MBCS)编码与UTF-8、Unicode编码...

    UTF-8转Unicode

    UTF-8的特点在于它对ASCII字符(如英文、数字等常见字符)使用单字节编码,与传统的ASCII编码兼容,而对于非ASCII字符则使用2到4个字节编码。这种设计使得UTF-8在处理多种语言混合的文本时效率较高,并且在网络传输...

    用PHP实现UTF-8和Unicode编码转换的技术.pdf

    首先,文章对UTF-8和Unicode的编码特征进行了分析,并探索了这两种编码之间的转换关系。然后,使用PHP语言实现了UTF-8和Unicode编码之间的转换函数,从而获得了使用PHP实现UTF-8和Unicode编码顺利转换的应用技术。 ...

    国际化字符转码器 unicode 转 utf-8 utf-8 转 unicode

    unicode -> utf-8 utf-8 -> unicode 国际化必备工具

    Delphi中UTF-8,Unicode格式转换

    delphi7调用delphi2009生成的dll文件会出现乱码问题。是unicode的原因 终于找到了UTF-8、Unicode格式转换函数

    UTF-8 Unicode GBK GB2312 编码之间的区别和联系

    本文将详细介绍UTF-8、Unicode、GBK以及GB2312这几种常见的字符编码方式,并探讨它们之间的区别与联系。 #### 二、基础知识 在深入讨论之前,我们需要先理解几个基本概念: 1. **字符编码**:是一种系统化的规则...

    utf-8.rar_c++ string utf-8_string to utf-8_utf_utf 8_utf-8

    在C++编程中,UTF-8编码是一种广泛使用的字符编码标准,它能够表示Unicode字符集中的所有字符。本文将深入探讨如何在C++中处理UTF-8字符串,并介绍相关的关键概念和技术。 首先,C++标准库并没有直接支持UTF-8编码...

    UTF-8toGBK_labview编码gbk_LabVIEWUTF-8_utf-8toGbk_

    UTF-8的优势在于对ASCII字符集的兼容性,前128个Unicode字符(包括英文、数字和常见符号)只需要一个字节表示,这使得UTF-8在互联网上广泛使用,因为其与ASCII的兼容性可以减少传输数据量。此外,UTF-8也支持全球大...

    UTF-8编码表

    如果UNICODE字符由2个字节表示,则编码成UTF-8很可能需要3个字节,而如果UNICODE字符由4个字节表示,则编码成UTF-8可能需要6个字节。用4个或6个字节去编码一个UNICODE字符可能太多了,但很少会遇到那样的UNICODE...

    字符编码转换类,支持 ANSI、Unicode、Unicode big endian、UTF-8、UTF-8+Bom互相转换

    "CharsetConv"类提供了一个工具,帮助开发者在ANSI、Unicode(Little Endian和Big Endian)、UTF-8及UTF-8+BOM之间灵活转换,从而避免编码问题带来的困扰。通过深入学习和实践,开发者可以更好地应对各种编码挑战,...

    UTF-8 UNICODE GBK 相互转换C源码

    在VS2005环境下,你可以使用C标准库中的`MultiByteToWideChar`和`WideCharToMultiByte`函数进行宽字符(UNICODE)与多字节字符(如GBK或UTF-8)之间的转换。同时,你需要包含`<windows.h>`头文件来使用这些函数。 ...

    文本文件编码转换:ANSI、Unicode、UTF-8相互转换(修改版)

    Unicode --> UTF-8 UTF-8 --> ANSI UTF-8 --> Unicode UTF-8 --> Unicode big endian ansi转别的,不检验BOM,一律作为ansi编码进行转换 unicode转别的,首先检验BOM,不合格不转换 utf8转别的,首先检验BOM,不...

    汉字字符编码(utf-8 unicode gb2312)

    对于常见的ASCII字符(如英文字符、数字、标点符号),UTF-8使用与ASCII相同的单字节编码,而对于非ASCII字符(如汉字),则使用更多的字节。UTF-8编码在互联网上广泛使用,因为它能很好地兼容原有的ASCII编码系统,...

    泰文UTF-8编码转成Unicode编码详细代码

    文件里有详细的代码,编码格式选择UTF-8编码,亲测在linux下可以直接运行。泰文在osd输出的流程一般是泰文先转换成Unicode编码,然后调用freetype进行文字渲染叠加

    lvgl unicode 转 utf-8小工具

    lvgl unicode 转 utf-8小工具

    大文本读取,使用API,可转换UTF-8,Unicode编码

    而UTF-8是Unicode的一种实现方式,是一种变长编码,它可以编码Unicode字符集中的所有字符,且在ASCII字符上与ASCII兼容,这使得UTF-8成为了互联网上最常用的编码格式。 当处理大文本文件时,普通的逐行读取可能会...

Global site tag (gtag.js) - Google Analytics