黑马程序员_I/O流(字符编码问题)

---------- android培训java培训、java学习型技术博客,期待与您交流!----------
        字符编码问题是程序开发中经常遇到的问题,造成的原因其实并不复杂,但需要注意避免和解决。
        先来回顾下在转换流中有所涉及过的字符编码。
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("utf.txt"),"UTF-8");
		char[] buf = new char[10];
		int len = isr.read(buf);
		String str = new String(buf,0,len);
		System.out.println(str);
		isr.close();
	}

	public static void writeText() throws IOException {
		OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("utf.txt"),"UTF-8");
		osw.write("你好");
		osw.close();
	}
}

        首先可以明确的是在平台下,中文默认是GBK编码,因此,无论是否指定编码要求为“GBK”,“你好”都会编码成4字节长的文件,而用UTF-8编码时,同样的“你好”文件就变成了6字节。如果以GBK编码写入却以UTF-8编码读取,会读取不出内容,反之则会读取出与原数据不相符的内容。这是由GBK编码用两个字节来表示中文而UTF-8编码用三个字节来表示中文造成的。
        参考上面的代码来概述一下编码解码原理和代码实现。编码就是字符串变成字节数组,解码就是字节数组变成字符串。String -->byte[ ]使用str.getBytes(charsetName),而byte[ ] -->String使用new String(byte[ ],charsetName)。示例代码如下:
import java.util.*;
class EncodeDemo{
	public static void main(String[] args) throws Exception {
		String s = "你好";
		byte[] b1 = s.getBytes("GBK");
		System.out.println(Arrays.toString(b1));

		String s1 = new String(b1,"ISO8859-1");
		System.out.println("s1="+s1);
		//对s1进行ISO8859-1编码
		byte[] b2 = s1.getBytes("ISO8859-1");
		System.out.println(Arrays.toString(b2));
		String s2 = new String(b2,"GBK");
		System.out.println("s2="+s2);
	}
}

        在上面的代码中,演示了如何在解码错误的情况下重新获取正确的数据。但是需要注意的是,如果编码时使用GBK编码表,解码时错误的使用了UTF-8的编码表,则原字节数组是无法这样还原的。究其原因,ISO8859-1编码表中没有中文编码,而UTF-8中是包含中文编码的,因此将GBK编码的字节数组用UTF-8错误的解码之后,再用UTF-8重新编码取不回原先的字节数组。
        最后看一个有趣的编码现象,也就可以理解UTF-8的编码判断了。新建一个文本文件,只输入“联通”,保存后关闭。再次打开该文件,会发现原本的内容“联通”变成了乱码。应用下面的代码,观察“联通”在GBK编码后的二进制字节数据就能看出端倪:
class EncodeDemo2{
	public static void main(String[] args) throws Exception {
		String s = "联通";
		byte[] by = s.getBytes("GBK");
		for(byte b : by){
			System.out.println(Integer.toBinaryString(b&255));
		}
	}
}

        原来,“联通”在被GBK编码后变成了:11000001,10101010,11001101,10101000。查询UTF-8的编码格式表后就能看出,原来其正好符合UTF-8编码表的格式规范。因此,明明是以GBK编码的“联通”在解码时被错误的识别为了UTF-8编码,所以也就无法正常显示原始数据了。
---------- android培训java培训、java学习型技术博客,期待与您交流!----------
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值