字符编码,就是对日常的控制符号、文字和常用符号的二进制表示。为了准确的表示如何编号,怎么生产八位字节流,Unicode Technical Report (UTR) #17提出现代编码模型的5个层次:

1.  抽象字符表:系统所支持的所有抽象字符的集合

2. 编码字符集:就是通过某种规则把抽象字符映射到编码空间的一个码位

3. 字符编码表:把码位转换成有限位长的整数值串,utf-8等。

4. 字符编码方案:把定长的整数转化为8bit

5. 传输编码语法:为了满足传输的需要,进一步处理字节流,base64就属于这一层。

字符编码也是随着计算机科学,信息科学的发展在不断发展的,从最初的标准ASCII,到后来的拓展ASCII,再到各国不同的编码,再到目前统一的unicode编码。

ASCII编码是最早1961年提出的,包含128个字符,其中95个可显示字符和33个控制字符(比如换行)。标准ASCII码使用一个字节中的7位存 储128个字符,最高位置0,ASCII 在平时的编码中只要记住一些典型的内容就可以了,比如0是48, A是65,a是97,大小写相差32。在标准ASCII之后IBM由于系统原因扩展了ASCII码,之后国际标准化组织又制定了 ISO2022 标准,它规定了在保持与 ISO646 兼容的前提下将 ASCII 字符集扩充为 8 位代码的统一方法。ISO针对不同的地区制定了不同的扩展ASCII码。

为了满足各国的需求,各国开始针对自身文字的需要制定相关的编码,这些编码大多使用两个字节来表示一个字符,这种编码被统一称为ANSI,比较有名的包括 gb2312(简体汉字编码表)、BIG5(繁体汉字编码)、GBK(gb2312扩展表)。杂乱的ANSI码之间并不能相互兼容,因为一个编码在不同的 ANSI编码中代表着不同的字符。在此环境下unicode编码产生了,他是基于把所有已知的文字、符号都纳入其中的思想建立的。

Unicode用0 ~ 0x10FFFF来映射这些字符, 一个可以存储1114112(2^20 + 2^16)个码位,unicode使用第一个字节来作为平面,目前有17个平面,平面15,16作为自定义区域预留,平面0也有一个专用 区:0xE000-0xF8FF,有6400个码位,同时平面0的0xD800-0xDFFF,共2048个码位,被称作代理区。Unicode表示效率 低下,故出现了多种对unicode编码的方式,比较有名的有utf-8,utf-16,utf-32 ,下面主要介绍下utf8与utf16。

UTF-8是以字节为单位对unicode编码的,utf-8对不同范围的码位采用不同的长度来编码:

unicode

字节码

000000 ~ 00007f 0xxxxxxx
000080 ~ 0007ff 110xxxxx 10xxxxxx
000800 ~ 007fff 1110xxxx 10xxxxxx 10xxxxxx
008000 ~ 10ffff 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

通过这种编码方式,可以保证在使用不同的字节编码,同时在解析的时候通过识别每个字节的前缀得知当前的字符是由几个字节组成的。

UTF-16是通过16位无符号数作为码元的编码方式。U+0000 ~ U+FFFF包含了常用的字符,UTF-16直接把这个范围的码位编码为对于的16位码元,对于U+10000 到 U+10FFFF的码位,编码成2个16位码元,编码方法代码如下:

    /**
* utf-16 编码算法, 大尾端
* @param offset 码位对于的值
* @return
*/
public String convertUTF16(int offset) {
if(offset < 0x10000) {
int vh = (offset & (0xFF << 8)) >> 8;//higt 8 bits
int vl = (offset & 0xFF);//low 8 bits
return Integer.toHexString(vh) + " " + Integer.toHexString(vl);
}
int val = offset - 0x10000;
int vh = (val & (0x3FF << 10)) >> 10;//higt 10 bits
int vl = (val & 0x3FF);//low 10 bits
int ph = 0xD800;//高位代理
int pl = 0xDC00;//地位代理
String firstSymbol = Integer.toHexString(ph + vh);
String secSymbol = Integer.toHexString(pl + vl);
return firstSymbol + " " + secSymbol;
}

对于多个字节表示,还有个问题,就是字节顺序(BIG-ENDIAN、LITTLE-ENDIAN),unicode采用bom(byte order mark)来区分,在传输流之前,先传输bom,unicode编码格式对应bom罗列如下:

utf编码方式 bom
utf-8 EF BB BF
utf-16 LE FF FE
utf-16 BE FE FF
utf-32 LE FF FE 00 00
utf-32 BE 00 00 FE FF

备注:utf-8由于其特殊的编码格式,并不需要bom来表示其字节顺序

关于java对于编码的处理,通过几个问题来阐明:

1. java的字节顺序是什么,BIG-ENDIAN or LITTLE-ENDIAN?

java是big-endian, 这个问题可以通过程序验证:

/**
* 检查字节顺序
* @throws UnsupportedEncodingException
*/
public String CheckByteOrder() throws UnsupportedEncodingException {
String a ="a";
byte[] arr = a.getBytes("utf-16");
if(arr[2] == 0) {//前两位为bom
return "big-endian";
} else if(arr[2] == 97) {
return "little-endian";
} else {
return "error";
}
}

2. java 中character编码方式?

在JAVA平台中,char[]、String、StringBuilder和StringBuffer类中采用了UTF-16编码,BMP字符用一个char表示,增补字符使用一对char表示。

3. java 的string.getBytes()方法获取字节使用的编码方式?

如api中所示,String.getBytes()方法使用的是默认编码,而这个编码方式和平台有关,可以通过如下方式获取平台的默认编码:

Charset.defaultCharset()

最后,StringBufferInputStream方法不建议使用,因为此类是早期的java类,read方法只获取char的低8位,会带来很多问题

public synchronized int read() {
return (pos < count) ? (buffer.charAt(pos++) & 0xFF) : -1;
}

字符编码介绍及java中的应用的更多相关文章

  1. 字符和字符串在Java中的旅程

    以下是个人对java中字符和字符串的见解,如有疏漏之处,还请不吝赐教. 下面通过一个简单的程序来说明字符和字符串在Java中的旅程. 以字符 ' 中 '为例, 它的GBK编码是2个字节:0xd6d0, ...

  2. Golang的字符编码介绍

    Golang的字符编码介绍 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. Go里面内建仅支持UTF8字符串编码,因此如果你用fmt.Printf之类的函数无法将GBK,GB2312 ...

  3. JAVA字符编码三:Java应用中的编码问题

    第三篇:JAVA字符编码系列三:Java应用中的编码问题 这部分采用重用机制,引用一篇文章来完整本部分目标. 来源:  Eceel东西在线 问题研究--字符集编码  地址:http://china.e ...

  4. python语言简介、解释器、字符编码介绍

    一.为什么要选择python作为学习语言: 各个语言的对比: C和python.java.C#等 C语言:代码编译得到机器码,机器码在处理器上直接执行,每一条指令控制cpu工作 其他语言:代码编译得到 ...

  5. 对字符串进行简单的字符数字统计 探索java中的List功能

    题目: 统计一个字符串中数字和字符串的个数,并分别进行排列,要求 1.数字,字符串可以从键盘获取. 2.储存在list 3.统计数字个数,字符串个数 4.把数字和字符串按从小到大的顺序输出 5.不能使 ...

  6. 对上次“对字符串进行简单的字符数字统计 探索java中的List功能 ”程序,面向对象的改进

    之前的随笔中的程序在思考后发现,运用了太多的static 函数,没有将面向对象的思想融入,于是做出了一下修改: import java.util.ArrayList; import java.util ...

  7. java中的字符集和编码

    前言 上次对计算机中的“字符集”和“编码”分别进行了总结,并指出二者之间的区别,不要搞混了,不清楚的再回到上一章看一下.今天再总结下java中是如何使用字符集(主要是Unicode字符集,其他常用字符 ...

  8. Java中的字节,字符与编码,解码

    ASCII编码 ASCII码主要是为了表示英文字符而设计的,ASCII码一共规定了128个字符的编码(0x00-0x7F),只占用了一个字节的后面7位,最前面的1位统一规定为0. ISO-8859-1 ...

  9. 理解Java中字符流与字节流的区别

    1. 什么是流 Java中的流是对字节序列的抽象,我们可以想象有一个水管,只不过现在流动在水管中的不再是水,而是字节序列.和水流一样,Java中的流也具有一个“流动的方向”,通常可以从中读入一个字节序 ...

随机推荐

  1. 格而知之9:一些关于GCD的笔记

    1.最近在重读当年刚开始学习多线程时的笔记,发觉其中有一些地方还是比较容易模糊,于是整理这篇笔记记录一下. 执行方式和队列 2.队列用来存放管理要执行的任务,它分为并发队列(Concurrent Di ...

  2. 如何彻底解决jsp页面中文乱码及数据库乱码

    最近自己闲做一个小项目,搭建环境框架SSH+MySQL数据库,遇到一个问题:jsp页面中文显示乱码,数据库插入数据和更新数据时中文也显示乱码,后来在网上找了许多解决方法,还是折腾了两天才把问题解决,下 ...

  3. cookie 和 session 基本使用 以及 封装

    Cookie: 是一小段文本信息,用户请求页面的时候,在浏览器和服务器之间传递.用户每次访问的时候都会记录cookie,cookie里可以包含用户信息,浏览的历史记录等等:Cookie是由服务器端生成 ...

  4. org.springframework.beans.factory.BeanCreationException

    org.springframework.beans.factory.BeanCreationException 这个是创建bean的异常. 我所遇到的情况是由下面这个引起的: @Resource an ...

  5. Js中JSON.stringify()与JSON.parse()与eval()详解及使用案例

    JSON(JavaScript Object Notation)是一种轻量级的数据交换格式.因为采用独立于语言的文本格式,也使用了类似于C语言家族的习惯,拥有了这些特性使使JSON称为理想的数据交换语 ...

  6. C# 读取xml节点类容

    这是一个测试节点类容的获取 这是控制台代码部分 注意的应用文件 :using.system.Xml using System; using System.Collections.Generic; us ...

  7. 如何让secureCRT显示Linux的颜色

    style="padding-bottom: 0px; line-height: 1.5; margin: 0px; padding-left: 0px; padding-right: 0p ...

  8. JQuery中如何动态修改input的type属性

    代码如下: jQuery(".member_id").focus(function() { jQuery(this).val(''); }).blur(function() { i ...

  9. python 数据类型之数float

    1.float 对象有一个重要的方法is_intger.如果这个float对应在转化为int时不会有精度的丢失就返回True,不然就返回False #!/usr/bin/python #!coding ...

  10. Nginx 配置指令的执行顺序(一)

    大多数 Nginx 新手都会频繁遇到这样一个困惑,那就是当同一个 location 配置块使用了多个 Nginx 模块的配置指令时,这些指令的执行顺序很可能会跟它们的书写顺序大相径庭.于是许多人选择了 ...