一、UTF-16编码方法
目前,UNICODE字符值的范围从U+000000到U+10FFFF(20bit),UTF-16以两个字节为单位对其进行编码。
1 字符值在U+0000到U+FFFF(注意U+D800到U+DBFF无定义)之间的字符(也叫做BMP, Basic Multilingual Plane),直接用两个字节表示。
2 字符值在U+10000到U+10FFFF(共有0xFFFFF个字符)之间的字符(也叫做增补字符集, supplementary characters),需要用四个字节表示。
前两个字节的范围是U+D800到U+DBFF(也叫高代理项, high-surrogates range),
后两个字节的范围是U+DC00到U+DFFF(也叫低代理项, low-surrogates range)。
转换方式如下:
1.1 将字符值减去0x10000,结果范围0x0000到0xFFFFF。
1.2 将结果的高10bit与0xD800做逻辑或运算,低10bit与0xDC00做逻辑或运算,
1.3 将两部分组合起来就是该字符值的UTF-16编码。
3 根据存储顺序的不同,UTF-16分为UTF-16LE和UTF-16BE,Windows和Linux一般使用UTF-16LE,而苹果操作系统使用UTF-16BE。
二、JAVA中的UTF-16
0 在JDK1.5之后JAVA才开始支持增补字符集,由JSR 204(Unicode Supplementary Character Support)实现。
1 JAVA中使用char(两个字节)作为表示字符的单位。因此,JAVA中单个char是无法表示增补字符的,而且位于U+D800到U+DBFF和U+DC00到U+DFFF的char被视为无定义字符。
2 在JAVA平台中,char[]、String、StringBuilder和StringBuffer类中采用了UTF-16编码,BMP字符用一个char表示,增补字符使用一对char表示。
3 JAVA使用代码点(Unicode code pointer)这个概念来表示范围在U+0000与U+10FFFF之间的字符值,代码单元(Unicode code unit)表示用于作为UTF-16编码的代码单元的 16位char值。因此,在Character类的API中,可以看到很多包含codePoint的方法。
4 String类中有关方法的分析
4.1 在String中,索引值指的是代码单元,所以增补字符在String中占两个位置。
4.2 int length()方法返回的是代码单元的数量,如果字符串中含有增补字符,该方法返回的值并非实际的字符数。
4.3 char charAt(int index)方法直接返回索引出的char值,不管该char是否为增补字符代理项。
4.4 int codePointAt(int index)方法,这个方法实际上是调用Character.codePointAtImpl()方法实现,源码如下
static int codePointAtImpl(char[] a, int index, int limit) { char c1 = a[index++]; if (isHighSurrogate(c1)) { if (index < limit) { char c2 = a[index]; if (isLowSurrogate(c2)) { return toCodePoint(c1, c2); } } } return c1; } 所以,当index和index+1均小于length(),且index的char在高代理范围内,就返回增补字符的代码点,否则返回index的char值。
4.5 int codePointBefore(int index),实际上调用Character.codePointBeforeImpl()方法。
static int codePointBeforeImpl(char[] a, int index, int start) { char c2 = a[--index]; if (isLowSurrogate(c2)) { if (index > start) { char c1 = a[--index]; if (isHighSurrogate(c1)) { return toCodePoint(c1, c2); } } } return c2; } 所以,当index-1和index-2均非负,且index-2的char在高代理范围内,index-1的char在低代理范围内,则返回增补字符的代码点,否则返回index-1的char值。
4.6 int codePointCount(int beginIndex, int endIndex),调用Character.codePointCountImpl()
static int codePointCountImpl(char[] a, int offset, int count) { int endIndex = offset + count; int n = 0; for (int i = offset; i < endIndex; ) { n++; if (isHighSurrogate(a[i++])) { if (i < endIndex && isLowSurrogate(a[i])) { i++; } } } return n; } 所以,该方法可以真正计算出字符串中的字符数量。
4.7 offsetByCodePoints(int index, int codePointOffset) 这个方法主要是计算从index开始,接下来第codePointOffset个代码点的下标。
4.8 int indexOf(int ch),其他相关方法,如lastIndexOf()等,原理类似。
如果ch的大小在0x0000到0xFFFF之间时,返回值是第一次满足charAt(k) == ch时的k值
如果ch的大小超过0xFFFF,返回值是第一次满足codePointAt(k) == ch的k值
如果都不满足,返回-1
关于以上这些函数的用法,developWorks上有篇文章有详细的解释:http://www.ibm.com/developerworks/cn/java/j-unicode/
相关资料:
unicode中文范围http://www.iteye.com/topic/558050
维基百科UTF-16词条http://zh.wikipedia.org/wiki/UTF-16
分享到:
相关推荐
Java避免UTF-8的csv文件打开中文出现...Java避免UTF-8的csv文件打开中文出现乱码的方法是使用UTF-16LE编码格式,并在文件头部输出BOM。同时,需要考虑Excel版本的兼容性问题,以确保csv文件可以正确地被打开和读取。
BOM的主要作用是在数据传输或存储时标识文件或数据流的字符编码,尤其是区分大端序(Big-Endian)和小端序(Little-Endian)的UTF-16编码。 在Java中,当我们从UTF-8编码的文本文件读取内容时,如果文件开头带有BOM...
最近的项目(Delphi开发),需要经常和java语言开发的系统进行数据交互(Socket通信方式),数据编码约定采用UTF-8编码。 令我无语的是:JAVA系统那边反映说,Delphi发的数据他们收到是乱码,而我这边(Delphi7,...
在Java中,UTF-8 支持国际化,是处理多种语言的理想选择,因为它具有良好的向后兼容性,并且通常不需要额外的转换。 ISO-8859-1,又称为Latin-1,是一种单字节编码,只包含西欧语言的基本拉丁字母。在处理英文为主...
在实际应用中,这种功能常用于编程语言的文本处理库,例如Python的`chardet`库,Java的`CharsetDetector`,或者C++的`ICU`库等,它们都提供了自动检测文件编码的方法。 了解并掌握文本文件的编码识别,对于进行跨...
文件里有详细的代码,编码格式选择UTF-8编码,亲测在linux下可以直接运行。泰文在osd输出的流程一般是泰文先转换成Unicode编码,然后调用freetype进行文字渲染叠加
JDK 中文转 utf-8 编码是 Java 开发中常见的问题,特别是在处理中文字符时。_utf-8 编码是一种通用的编码方式,可以表示所有 Unicode 字符。在 JDK 中提供了一个工具 native2ascii.exe,可以将中文字符转换为 utf-8 ...
在Java JSP开发中,遇到UTF-8编码导致的乱码问题是一个常见的困扰。这个问题主要涉及到字符编码的统一和正确处理。UTF-8是一种广泛使用的Unicode字符编码方案,它可以支持几乎所有的字符集,包括中文、日文和韩文。...
在Java中,`String`类的`getBytes()`方法可以将字符串转换为字节数组,但默认编码通常是平台的默认编码,可能不是UTF-8。为了确保使用UTF-8编码,我们需要指定`Charset`参数,如`getBytes("UTF-8")`。 以下是一个...
本文将详细介绍几种常见的字符编码(Unicode, ISO-8859-1, GBK, UTF-8)及其在Java中的应用,并讨论它们之间的相互转换方法。 #### 1. Unicode Unicode是一种国际标准字符集,它为每一个字符分配了一个唯一的数字,...
Unicode最常用的变体是UTF-8、UTF-16等。在Java中,字符串默认使用Unicode编码,每个字符通常占用两个字节。 ##### 2. ISO-8859-1 ISO-8859-1是一种单字节编码方案,主要用于西欧语言。每个字符由一个字节表示,...
Java字符串编码查询及转换,可将常用的一些编码格式转换成utf-8
XML的编码问题不仅限于UTF-8,还有其他的Unicode编码如UTF-16,或者更早期的ISO-8859-1等。然而,由于UTF-8的广泛支持和效率优势,它已成为XML文件的首选编码。 总之,XML文件的处理涉及到了编码的读取、写入和转换...
在处理中文和英文混合的数据时,它能够正确地支持UTF-8编码,确保跨语言平台的一致性,如Java、PHP、Python和JavaScript。 HMAC(Hash-based Message Authentication Code)是一种基于哈希函数的消息认证码,用于...
在"jmeter5.0官网utf-8编码"这个主题中,我们关注的是JMeter 5.0版本,并且源码已经修改为UTF-8编码,以解决在使用过程中可能出现的字符乱码问题。 JMeter 5.0是Apache JMeter的一个重大更新,它引入了多项改进和新...
不需要关心接受的字符串编码是UTF_8还是GBK,还是ios-8859-1,自动转换为utf-8编码格式,无需判断字符串原有编码,用法://处理编码String newStr = GetEncode.transcode(oldStr);
该程序支持.c .h .cpp .hpp .bat .java等6种格式的文件编码转换,如果需要添加其他格式的文件,直接修改suffix的条件判断处的语句即可,压缩包中提供exe程序和python写的源码
老项目采用GBK编码格式,而新项目采用的UTF-8编码格式,如果直接把Java源代码复制到Eclipse中所有的中文信息会出现乱码。所以写了个小的方法类,将java文件的编码格式从GBK转UTF-8
JAVA UTF-8编码中文转拼音附件上传