您的位置:首页 > 其它

IO流__【转换流的字符编码】【编码与解码】【字符编码-“联通”】

2014-01-01 10:02 246 查看

常见的码表

ASCII:美国标准信息交换码。用一个字节7位可以表示。
ISO8859-1:拉丁码表。欧洲码表用一个字节8位表示。
GB2312:中国的中文编码表。
GBK:中国的中文编码表升级,融合了更多的中文文字符号。
Unicode:国际标准码,融合了多种文字。所有文字都用两个字节来表示,Java语言就是unicode
UTF-8:最多用三个字节来表示一个字符。

转换流的字符编码

示例 :

import java.io.*;
class  EncodeStream
{
	public static void main(String[] args) throws IOException
	{
//		writeText();
		readText();
	}
	public static void readText() throws IOException{
		InputStreamReader isr = new InputStreamReader(new FileInputStream("gbk.txt"),"GBK");//转换流按照指定码表解码
		char[] buf = new char[8];
		int len = isr.read(buf);
		String s = new String(buf,0,len);
		System.out.println(s);
		isr.close();
	}
	public static void writeText() throws IOException{
		OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("UTF-8.txt"),"UTF-8");//转换流按指定码表编码
		osw.write("你好");
		osw.close();		
	}
}
调用writeText();方法;将转换流编码分别指定为(("GBK.txt"),gbk)和(("UTF-8.txt",UTF-8)),生成GBK和UTF-8两个txt文档;

发现同样是“你好”两个字符,UTF-8编码的占了6个字节,gbk编码的占了4个字节



调用readText();方法;

当其各自按照各自指定的码表解码时都能够读取出“你好”;当其按照非指定的码表解码时会产生乱码(左图);“你好”在GBKUTF-8两种编码中的字节数组(右图)





分析原因图解:其各自的编解码方式不同导致了结果



-------------------------------------------------------------------------------------------------------------------------------

编码与解码:

编码:字符串变成字节数组;String -->byte[];
(String类的方法):str.getBytes(charsetName);;将该字符串按照指定编码表编码。

解码:字节数组变成字符串;byte[] -->String;
(String类的构造方法):new String(byte[],charsetName);通过使用指定的
charset 解码指定的 byte 数组。

方法空参则代表使用系统默认的编码表,中文为GBK,设定charsetName可以用指定的编码表

编码与解码示例:

import java.util.*;	//Arrays类
class  EncodeDemo
{
	public static void main(String[] args) throws Exception
	{
		String s = "你好";
		byte[] b1 = s.getBytes("GBK");//GBK编码
		sop(Arrays.toString(b1));
		String s1 = new String(b1,"ISO8859-1");	//解码,码表不对应,产生乱码
		sop("s1:"+s1);
		byte[] b2 = s1.getBytes("ISO8859-1");	//将其解码出的乱码再次编码,字节数组
		sop(Arrays.toString(b2));
		String s2 = new String(b2,"GBK");//解码
		sop("s2:"+s2);
	}
	public static void sop(Object obj){
		System.out.println(obj);
	}
}


运行结果:



图解:



实际应用场景:客户端与服务器端的码表不一致,例如一个服务器端的网页在客户端打开时就可能会产生乱码,所以要加上一个编码与解码的过程,避免这种情况的发生

开发中会经常遇到这种情况,要注意!

注意事项:

GBK不能用UTF-8作为中间码来编解码,如果将上文EncodeDemo中“ISO8859-1”改成“utf-8”

运行结果:



产生这种结果的原因是:UTF-8一个字符所占的字节个数比GBK(2个)要多,utf-8解码后的乱码经其再次编译后产生的字节数组与GBK编译后的字节数组不一致

要避免这种情况。

字符编码-“联通”

在空记事本上输入“联通”两个字,保存后再次打开,会发现只有两个乱码

首先要了解UTF-8修改版特点:

两个字节110开头,三个字节1110开头



通过打印其字节数组和二进制位:

import java.util.*;
class  EncodeDemo2
{
	public static void main(String[] args) throws Exception//加入编码表会抛异常
	{
		String s = "联通";
		byte[] by = s.getBytes("gbk");	//gbk编码
		sop(Arrays.toString(by));	//打印字节数组
		for (byte b:by ){
			sop(Integer.toBinaryString(b&255));//打印字节数组的二进制位
		}
	}
	public static void sop(Object obj){
		System.out.println(obj);
	}
}
运行结果:



分析:通过“联通”的字节数组的二进制位发现:其刚好UTF-8两个字符的标准,所以原本是GBK编码的文件在再次打开时成了UTF-8解码,所以造成了乱码

在简体中文操作系统中默认的本地字符集编码是GBK编码,除非你在保存记事本文本文件时候选择了其他编码方式,否则用记事本录入的字符信息将使用GBK编码进行储存。巧合的是,“联通”这两个字符的GBK编码具有UTF-8编码的特征,记事本犯下的错误正是将GBK编码存放的记录有“联通”两个字符的文件误认为UTF-8编码的文件。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: