`
vyloy
  • 浏览: 78680 次
  • 性别: Icon_minigender_1
  • 来自: 佛山
社区版块
存档分类
最新评论

字节、字符串与字符编码

    博客分类:
  • Java
阅读更多
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 缓冲区
分享到:
评论

相关推荐

    c#与编码无关的字符串与字节数组相互转换

    web应用中,客户端和服务器端需要交换信息,字符串形式的信息交互是...如果字符串中有中文,客户端在信息发送前需要把它转换为字节数组,转换的时候需要采用指定的编码。 本文提供的方法不需要指定编码,是通用的方法。

    Delphi中处理字符串的相关方法

    Delphi中处理字符串的相关方法 1、字符集转换方法 (1)stringtowidechar function stringtowidechar(const ...将sourcelen长度的unicode编码字符串转换为单字节或多字节字符串。实际的转换是通过调用win32 API函数

    C++实现判断一个字符串是否为UTF8或GBK格式的方法

    本文实例讲述了C++实现判断一个字符串是否为UTF8或GBK格式的方法。分享给大家供大家参考,具体如下: ...//UFT8可用1-6个字节编码,ASCII用一个字节 unsigned char chr = *str; bool bAllAscii = t

    C#获取字符串的字节数

    C#根根据不同的字符编码方式获取字符串的字节数

    图片文件与Base64编码字节数组字符串互转

    图片文件与Base64编码字节数组字符串互转

    中英文字符串分割算法C++C程序示例

    <Rule.4>: (基于R3)如果第pos个位置的ASCII字符编码小于'~', 那从下标pos,pos+1处拆分字符串 (下标pos归前串),将不会导致乱码; A 或者 B 的选择,需要知道以下信息: (1). 从 cut_base_pos 开始到 pos_B 结束...

    python实现字符串加密成纯数字

    1.字符串以utf8编码成字节数组 2.把每一个字节转换成十进制数字字符串(‘0’~’255’) 3.在每个十进制数字字符串之前加上一个长度位(长度位固定只占1个字符) 4.进行数字替换,例如:(0-1,1-9,2-3,3-8,4-7,5-6...

    Java字符流与字节流区别

    字符流处理的单元为 2 个字节的 Unicode 字符,分别操作字符、字符数组或字符串,而字节流处理单元为 1 个字节,操作字节和字节数组。 Java 内用 Unicode 编码存储字符,字符流处理类负责将外部的其他编码的字符流...

    C#简单判断字符编码的方法

    本文实例讲述了C#简单判断字符编码的方法。分享给大家供大家参考,具体如下: public static string GetText(byte[] buff) { string strReslut = string.Empty; if (buff.Length > 3) { if (buff[0] == 239 && ...

    基64字节数组转基64字符串

    在web项目的前后台图片交互中,用的是基64...前台可以向后台传递基64字符串或者基64字节数组。后台也可以向前台传递基64字符串或者基64字节数组。下面的函数将基64字节数组转换成基64字符串,可以添加到img中显示图片。

    C#(.net)中按字节数截取字符串最后出现乱码问题的解决

    最近需要用到按字节数截取字符串。在网上找了很多方法。 Encoding.Default.GetString采用的Default Encoding.UTF8.GetBytes采用的是utf-8编码。这样当然是乱码。尤其出现中文时候。 对这类数据处理当然要用统一的...

    unicode格式的字符串进行URL编码

    但是找遍了精易模块和百度都没有说有这这个命令 让Unicode字符串(易语言里面以字节集表示)直接进行正确的URL编码。所以就自己写了一个JavaScript脚本 进行URL编码。原理就是先把unicode字符串转换成BASE64编码文本。...

    C++字符串完全指引之Win32字符编码

    传统Ansi(单字节字符)和Unicode(双字节字符,又称为宽字符)介绍以及Win32对它们的支持.

    Python中字符串与编码示例代码

    在最新的Python 3版本中,字符串是以Unicode编码的,即Python的字符串支持多语言 编码和解码  字符串在内存中以Unicode表示,在操作字符串时,经常需要str和bytes互相转换  如果在网络上传输或保存到磁盘上,则从...

    字符串转16进制码

    详细: 1. 输入一串字符串生成一串16进制编码 2. 有可能生成的最后一个编码是没有用的 3. 用处:例如打印时需要传16进制编码测试一下就可以用上。

    UTF8,ANSI,UTF7,UNICODE,UTF32等字符集字符串与字节数组互转工具

    UTF8,ANSI,UTF7,UNICODE,UTF32等字符集字符串与字节数组互转工具,方便调试学习

    PHP中字符与字节的区别及字符串与字节转换示例

    字符: 字符是可使用多种不同字符方案或代码页来表示的抽象实体。例如,Unicode UTF-16 编码将字符表示为 16 位整数序列,而 Unicode UTF-8 编码则将相同的字符表示为 8 位字节序列。...下面看下PHP字符串与

    字符串截取

    根据指定字节数截取字符串,当指定处为中文第一个字节时少截取一个字符,当长度大于指定截取长度时,截取后在字符串末尾追加指定字符串 * 这里添加了字符串的编码,因为页面的编码不同,字符串所占字节

    ASCII/GB2312/UTF-8/Unicode编码 字符串与字节转换查看源码

    ASCII/GB2312/UTF-8/Unicode编码 字符串与字节转换查看源码。采用Visual Studio 2008开发,使用C# Windows Form编写,代码简单易懂。 输入:CSDN-全球最大中文IT社区。 选择:GB2312 结果:4353444E2DC8ABC7F2D7EEB...

Global site tag (gtag.js) - Google Analytics