从java string实例来理解ansi、unicode、bmp、utf等编码概念

从java string实例来理解ansi、unicode、bmp、utf等编码概念

ID:6036832

大小:408.13 KB

页数:12页

时间:2017-12-31

从java string实例来理解ansi、unicode、bmp、utf等编码概念_第1页
从java string实例来理解ansi、unicode、bmp、utf等编码概念_第2页
从java string实例来理解ansi、unicode、bmp、utf等编码概念_第3页
从java string实例来理解ansi、unicode、bmp、utf等编码概念_第4页
从java string实例来理解ansi、unicode、bmp、utf等编码概念_第5页
资源描述:

《从java string实例来理解ansi、unicode、bmp、utf等编码概念》由会员上传分享,免费在线阅读,更多相关内容在行业资料-天天文库

1、从JavaString实例来理解ANSI、Unicode、BMP、UTF等编码概念一、前言一切的谜都解开了!在写这篇随笔之前,我的心情只能用金田一每次破案后的这句台词来表达。其实从开始写Java代码以来,遇到过无数次乱码与转码问题,比如从文本文件读入到String出现乱码,JSP获取HTTP请求参数出现乱码等问题,由于这些问题很常见,遇到的时候随手百度一下一般都可以顺利解决。也曾尝试过去把概念理清楚,但网上众说纷纭,内容繁杂,又不愿意花精力去看标准文档,所以问题搁置了很久。前两天同学与我谈起一个Java源文件的编码问题(这问题在最

2、后一个实例分析),从这个问题入手拉扯出了一连串的问题,然后我们一边查资料一边讨论,直到深夜,终于在一篇博客中找到了关键性线索,解决了所有的疑惑,以前没有理解的语句都能解释清楚了。因此我决定用这篇随笔,记录我对一些编码问题的理解以及实验的结果。下面有些概念是我自己结合实际的理解,如果有误,请一定不吝指正。二、概念总结早期,互联网还没有发展起来,计算机仅用于处理一些本地的资料,所以很多国家和地区针对本土的语言设计了编码方案,这种与区域相关的编码统称为ANSI编码(因为都是对ANSI-ASCII码的扩展)。但是他们没有事先商量好怎么相互

3、兼容,而是自己搞自己的,这样就埋下了编码冲突的祸根,比如大陆使用的GB2312编码与台湾使用的Big5编码就有冲突,同样的两个字节,在两种编码方案里表示的是不同的字符,随着互联网的兴起,一个文档里经常会包含多种语言,计算机在显示的时候就遇到麻烦了,因为它不知道这两个字节到底属于哪种编码。这样的问题在世界上普遍存在,因此重新定义一个通用的字符集,为世界上所有字符进行统一编号的呼声不断高涨。由此Unicode码应运而生,它为世界上所有字符进行了统一编号,由于它可以唯一标识一个字符,所以字体也只需要针对Unicode码进行设计就行了。但

4、Unicode标准定义的是一个字符集,而没有规定编码方案,也就是说它仅仅定义了一个个抽象的数字与其对应的字符,而没有规定具体怎么存储一串Unicode数字,真正规定怎么存储的是UTF-8、UTF-16、UTF-32等方案,所以带有UTF开头的编码,都是可以直接通过计算和Unicode数值(CodePoint,代码点)进行转换的。顾名思义,UTF-8就是8位长度为基本单位编码,它是变长编码,用1~6个字节来编码一个字符(因为受Unicode范围的约束,所以实际最大只有4字节);UTF-16是16位为基本单位编码,也是变长编码,要么2

5、个字节要么4个字节;UTF-32则是定长的,固定4字节存储一个Unicode数。其实我以前一直对Unicode有点误解,在我的印象中Unicode码最大只能到0xFFFF,也就是最多只能表示2^16个字符,在仔细看了维基百科之后才明白,早期的UCS-2编码方案确实是这样,UCS-2固定使用两个字节来编码一个字符,因此它只能编码BMP(基本多语言平面,即0x0000-0xFFFF,包含了世界上最常用的字符)范围内的字符。为了要编码Unicode大于0xFFFF的字符,人们对UCS-2编码进行了拓展,创造了UTF-16编码,它是变长的

6、,在BMP范围内,UTF-16与UCS-2完全一致,而BMP之外UTF-16则使用4个字节来存储。为了方便下面的描述,先交代一下代码单元(CodeUnit)的概念,某种编码的基本组成单位就叫代码单元,比如UTF-8的代码单元为1个字节,UTF-16的代码单元为2个字节,不好解释,但是很好理解。为了兼容各种语言以及更好的跨平台,JavaString保存的就是字符的Unicode码。它以前使用的是UCS-2编码方案来存储Unicode,后来发现BMP范围内的字符不够用了,但是出于内存消耗和兼容性的考虑,并没有升到UCS-4(即UTF-

7、32,固定4字节编码),而是采用了上面所说的UTF-16,char类型可看作其代码单元。这个做法导致了一些麻烦,如果所有字符都在BMP范围内还没事,若有BMP外的字符,就不再是一个代码单元对应一个字符了,length方法返回的是代码单元的个数,而不是字符的个数,charAt方法返回的自然也是一个代码单元而不是一个字符,遍历起来也变得麻烦,虽然提供了一些新的操作方法,总归还是不方便,而且还不能随机访问。此外,我发现Java在编译的时候还不会处理大于0xFFFF的Unicode字面量,所以如果你敲不出某个非BMP字符来,但是你知道它的

8、Unicode码,得用一个比较笨的方法来让String存储它:手动计算出该字符的UTF-16编码(四字节),把前两个字节和后两个字节各作为一个Unicode数,然后赋值给String,示例代码如下所示。1234567publicstaticvoid

当前文档最多预览五页,下载文档查看全文

此文档下载收益归作者所有

当前文档最多预览五页,下载文档查看全文
温馨提示:
1. 部分包含数学公式或PPT动画的文件,查看预览时可能会显示错乱或异常,文件下载后无此问题,请放心下载。
2. 本文档由用户上传,版权归属用户,天天文库负责整理代发布。如果您对本文档版权有争议请及时联系客服。
3. 下载前请仔细阅读文档内容,确认文档内容符合您的需求后进行下载,若出现内容与标题不符可向本站投诉处理。
4. 下载文档时可能由于网络波动等原因无法下载或下载错误,付费完成后未能成功下载的用户请联系客服处理。