Unicode的问题
需要注意的是,
Unicode只是一个符号集,它只规定了符号的二进制代码,却没有规定这个二进制代码应该如何存储。
比如,汉字“严”的unicode是十六进制数4E25,转换成二进制数足足有15位(100111000100101),也就是说这个符号的表示至少需要2个字节。表示其他更大的符号,可能需要3个字节或者4个字节,甚至更多。
这里就有两个严重的问题,
第一个问题是,如何才能区别unicode和ascii?计算机怎么知道三个字节表示一个符号,而不是分别表示三个符号呢?第二个问题是,我们已经知道,英文字母只用一个字节表示就够了,如果unicode统一规定,每个符号用三个或四个字节表示,那么每个英文字母前都必然有二到三个字节是0,这对于存储来说是极大的浪费,文本文件的大小会因此大出二三倍,这是无法接受的。
它们造成的结果是:1)
出现了unicode的多种存储方式,也就是说有许多种不同的二进制格式(utf-8,gbk),可以用来表示unicode。2)unicode在很长一段时间内无法推广,直到互联网的出现。
Unicode符号范围 | UTF-8编码方式
(十六进制) | (二进制)
--------------------+---------------------------------------------
0000 0000-0000 007F | 0xxxxxxx
0000 0080-0000 07FF | 110xxxxx 10xxxxxx
0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx
0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
下面,还是以汉字“严”为例,演示如何实现UTF-8编码。
已知“严”的unicode是4E25(100111000100101),根据上表,可以发现4E25处在第三行的范围内(0000 0800-0000 FFFF),因此“严”的UTF-8编码需要三个字节,即格式是“1110xxxx 10xxxxxx 10xxxxxx”。然后,从“严”的最后一个二进制位开始,依次从后向前填入格式中的x,多出的位补0。这样就得到了,“严”的UTF-8编码是“11100100 10111000 10100101”,转换成十六进制就是E4B8A5。
================================================================
首先,要搞清楚 code point 和 encoding 的区别。Java 是遵循 unicode 4.0 标准的,而内部的 character 以 utf-16 作为 encoding。unicode 4.0 标准包含从 U+0000-U+FFFF 的基本多语言平面和 U+10000-U+10FFFF 的扩展平面的文字,这是 code point。Java 的 char 类型是 16 bit 的,所以单个 char 只支持基本平面内的文字,而扩展平面的文字是由一对 char 来表示的。
而 String.getBytes() 这个方法是按照指定的 encoding 返回字符串,一般中文系统的默认编码是 utf-8 (linux, mac) 或者 gbk/gb18030 (windows)。只要是基本平面内的文字,utf-8码的中文都是3字节的,而 gbk/gbk18030 是2字节的。
================================================================
char c='你';
System.out.print(Integer.toHexString(c));
System.out.println(" "+Integer.toBinaryString(c));
String s=Character.toString(c);
//用utf-8进行编码后的字节数组内容
for(byte b:s.getBytes("utf-8")){
System.out.print(Integer.toHexString(b));
System.out.println(" "+Integer.toBinaryString(b));
}
System.out.println("---------------");
//用gb2312进行编码后的字节数组内容
byte[] gbb = new String(s.getBytes("utf-8"),"utf-8").getBytes("gb2312");
for(byte b:gbb){
System.out.print(Integer.toHexString(b));
System.out.println(" "+Integer.toBinaryString(b));
}
//从Unicode转化为byte[]
s = new String(gbb,"gb2312");//由于gbb字节数组是经过gb2312编码,必须先解码还原成为Unicode
ByteBuffer byteBuffer = ByteBuffer.allocate(6);
CharBuffer charBuffer = byteBuffer.asCharBuffer();
charBuffer.put(s);
//用asCharBuffer()方法创建的视图与原buffer的位置、界限和标记值是相互独立的
//例如这里,byteBuffer.position()==0,所以要先设置position再flip,
byteBuffer.position(charBuffer.position()*2);
System.out.println(byteBuffer);
byteBuffer.flip();
System.out.println(byteBuffer);
System.out.println(charBuffer.flip());
while(byteBuffer.hasRemaining()){
byte b = byteBuffer.get();
System.out.print(Integer.toHexString(b));
System.out.println(" "+Integer.toBinaryString(b));
}
输出如下:
4f60 100111101100000
ffe4 11111111111111111111111111100100
ffbd 11111111111111111111111110111101
ffa0 11111111111111111111111110100000
---------------
ffffffc4 11111111111111111111111111000100
ffffffe3 11111111111111111111111111100011
java.nio.HeapByteBuffer[pos=2 lim=6 cap=6]
java.nio.HeapByteBuffer[pos=0 lim=2 cap=6]
你
4f 1001111
60 1100000
ByteBuffer的asCharBuffer方法
asCharBuffer
public abstract CharBuffer asCharBuffer()创建此字节缓冲区的视图,作为 char 缓冲区。
新缓冲区的内容将从此缓冲区的当前位置开始。此缓冲区内容的更改在新缓冲区中是可见的,反之亦然;这两个缓冲区的位置、界限和标记值是相互独立的。
新缓冲区的位置将为零,其容量和界限将为此缓冲区中所剩余的字节数的二分之一,其标记是不确定的。当且仅当此缓冲区为直接时,新缓冲区才是直接的,当且仅当此缓冲区为只读时,新缓冲区才是只读的。
返回:
新的 char 缓冲区
分享到:
相关推荐
web应用中,客户端和服务器端需要交换信息,字符串形式的信息交互是...如果字符串中有中文,客户端在信息发送前需要把它转换为字节数组,转换的时候需要采用指定的编码。 本文提供的方法不需要指定编码,是通用的方法。
Delphi中处理字符串的相关方法 1、字符集转换方法 (1)stringtowidechar function stringtowidechar(const ...将sourcelen长度的unicode编码字符串转换为单字节或多字节字符串。实际的转换是通过调用win32 API函数
本文实例讲述了C++实现判断一个字符串是否为UTF8或GBK格式的方法。分享给大家供大家参考,具体如下: ...//UFT8可用1-6个字节编码,ASCII用一个字节 unsigned char chr = *str; bool bAllAscii = t
C#根根据不同的字符编码方式获取字符串的字节数
图片文件与Base64编码字节数组字符串互转
<Rule.4>: (基于R3)如果第pos个位置的ASCII字符编码小于'~', 那从下标pos,pos+1处拆分字符串 (下标pos归前串),将不会导致乱码; A 或者 B 的选择,需要知道以下信息: (1). 从 cut_base_pos 开始到 pos_B 结束...
1.字符串以utf8编码成字节数组 2.把每一个字节转换成十进制数字字符串(‘0’~’255’) 3.在每个十进制数字字符串之前加上一个长度位(长度位固定只占1个字符) 4.进行数字替换,例如:(0-1,1-9,2-3,3-8,4-7,5-6...
字符流处理的单元为 2 个字节的 Unicode 字符,分别操作字符、字符数组或字符串,而字节流处理单元为 1 个字节,操作字节和字节数组。 Java 内用 Unicode 编码存储字符,字符流处理类负责将外部的其他编码的字符流...
本文实例讲述了C#简单判断字符编码的方法。分享给大家供大家参考,具体如下: public static string GetText(byte[] buff) { string strReslut = string.Empty; if (buff.Length > 3) { if (buff[0] == 239 && ...
在web项目的前后台图片交互中,用的是基64...前台可以向后台传递基64字符串或者基64字节数组。后台也可以向前台传递基64字符串或者基64字节数组。下面的函数将基64字节数组转换成基64字符串,可以添加到img中显示图片。
最近需要用到按字节数截取字符串。在网上找了很多方法。 Encoding.Default.GetString采用的Default Encoding.UTF8.GetBytes采用的是utf-8编码。这样当然是乱码。尤其出现中文时候。 对这类数据处理当然要用统一的...
但是找遍了精易模块和百度都没有说有这这个命令 让Unicode字符串(易语言里面以字节集表示)直接进行正确的URL编码。所以就自己写了一个JavaScript脚本 进行URL编码。原理就是先把unicode字符串转换成BASE64编码文本。...
传统Ansi(单字节字符)和Unicode(双字节字符,又称为宽字符)介绍以及Win32对它们的支持.
在最新的Python 3版本中,字符串是以Unicode编码的,即Python的字符串支持多语言 编码和解码 字符串在内存中以Unicode表示,在操作字符串时,经常需要str和bytes互相转换 如果在网络上传输或保存到磁盘上,则从...
详细: 1. 输入一串字符串生成一串16进制编码 2. 有可能生成的最后一个编码是没有用的 3. 用处:例如打印时需要传16进制编码测试一下就可以用上。
UTF8,ANSI,UTF7,UNICODE,UTF32等字符集字符串与字节数组互转工具,方便调试学习
字符: 字符是可使用多种不同字符方案或代码页来表示的抽象实体。例如,Unicode UTF-16 编码将字符表示为 16 位整数序列,而 Unicode UTF-8 编码则将相同的字符表示为 8 位字节序列。...下面看下PHP字符串与
根据指定字节数截取字符串,当指定处为中文第一个字节时少截取一个字符,当长度大于指定截取长度时,截取后在字符串末尾追加指定字符串 * 这里添加了字符串的编码,因为页面的编码不同,字符串所占字节
ASCII/GB2312/UTF-8/Unicode编码 字符串与字节转换查看源码。采用Visual Studio 2008开发,使用C# Windows Form编写,代码简单易懂。 输入:CSDN-全球最大中文IT社区。 选择:GB2312 结果:4353444E2DC8ABC7F2D7EEB...