java编码详解

来源:互联网 发布:一氧化二氮 淘宝 编辑:程序博客网 时间:2024/05/16 19:35

0 引子

最近在写一个web框架,实现MVC模式中Contrl的主要功能,其实也就是练手的,毕竟还是觉得实践是最好的老师(但是,算法之心不死啊~~~~),之前也写过一个模板渲染引擎,目前也在不断完善中。在两个项目中最大的头疼问题还是编码,以及java中众多的IO类,所以这次找了详细的编码资料,记录一下。

1 什么是编码

计算机的基本运算单位是字节(8 bit),但是人类语言文字有很多种,所以当计算机用来存储语言的文字时仅仅使用一个字节显然是不行的,因为一个字符最多有256种表示形式。所以为了在计算机中显示多种字码,需要对不同的文字有不同的编码,方便存储在计算机中。

2 编码类型

1. ASCII码

学过计算机都知道的,用一个字节表示,总共有128个,在这我就不多说了。

2. ISO-8859-1

显然128个字符是不够用的,于是ISO组织在ASCII码的基础上有制定了一系列的标准来扩展ASCII码,包括ISO-8859-1至ISO-8859-15,其中ISO-8859-1涵盖了大多数西欧的语言文字,所以应用的最为广泛,同时ISO-8859-1为单个字节,一共256个。

3. GB2312

GB2312的全称是《信息技术 中文编码字符集》,它使用双字节编码,编码范围是A1-F7,其中A1-A9是符号区,包括6763个汉字。

4. GBK

GBK全称是《汉字内码扩展规范》,是国家技术监督局为windows 95所制定的新的汉字内码规范,它是为了扩展GB2312,加入更多的汉字。所以它和GB2312是向后兼容的。所以用GB2312编码的汉字可以使用GBK解码,不会乱码。

5. GB18030

GB18030的全称是《信息技术 中文编码字符集》,是我国的强制标准,可以是单字节,双字节或者四字节,他的编码与GB2312编码兼容,虽然是国家标准,但是在实际应用中并不广泛。

6. UTF-16

说道UTF必须要说道Unicode(Universal Code 统一码),ISO试图创建一个全新的超语言字典,使得世界上所有的语言都可以通过这个字典互相翻译。可想而知这个编码是多么复杂。这里不做详细介绍,但是Unicode是java和XML的基础。

UTF-16是定义了Unicode的字符在计算机中存取方法。UTF-16使用两个字节转化Unicode的格式,它采用定长的方法,即所有字符都是两个字节。因为所有字符都是两个字节,所以大大的简化了字符串操作,所以Java是以UTF-16作为内存字符存储格式。

7. UTF-8

由于统一使用两个字符表示占用很多无用的空间,所以UTF-8采用变长技术,每个编码区都有不同的字码长度,不同的类型编码可以由1-6个字节组成。具体的规则不作详细说明。

3 字符与字节

在Java中,字符类型char是两个字节,而字节类型byte是一个字节,这是两个不同的概念,一个在计算机中显示的字符在Java虚拟机中是两个字节表示的,但是在文件中可能占用一个字节或者多个字节。当Java读取文件时,如果指定的编码不正确,读取每个字符char时不能正确读取相应的字节数。

4 Java中的IO操作

在Java众多的IO类中,有一个专门负责编码的父类Reader,它主要负责字节到字符的转化,负责在IO过程中处理读取字节到字符的转换。同理父类Writer类是负责IO过程中字符写到字节的转换。在具体实践中,如果你没有指定具体的字符集,那么系统将会加载本地默认字符集,比如在中文环境中使用GBK编码。我在IDEA中编写Web框架的一个项目中就遇到过这个问题,本地的模板文件编码是UTF-8,而没有指定读取文件的编码类型,导致默认使用GBK编码读取,导致乱码(原谅我的无知~~~)。

5 一个例子

FileInputStream fileInputStrea = new FileInputStram("example.txt");InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream,"utf-8");//使用“UTF-8”编码读取文件StringBuffer stringBuffer = new StringBuffer();char[] buffer  = new char[32];int len = 0;try {    while ((len = inputStreamReader.read(buffer)) != -1){        stringBuffer.append(buffer,0,len);    }}finally {    inputStreamReader.close();}

上述代码可以简单解释编码在IO中的作用,在读取文件(“UTF-8”编码)在buffer数组(“UTF-16”编码)中。如果不指定编码类型,默认使用“GBK”编码解码,读取的文件肯定是要乱码的。

总之,Java在读取字节文件时,会按照指定编码情况将其文件中的字符转化为UTF-16编码存储在内存中(char类型),随后进行相关操作。所以在文件编码方面一定要特殊注意。

值得一提的是不同类型解码和编码是常常有不能处理的情况,比如某些字符不能识别,那么就会生成默认的字节数据,导致最后可能出现“?????”或者“烫烫烫”等等有意思的字符。

0 0