黑马程序员技术交流社区

标题: 麻烦各位帮我详细解释下这个代码? [打印本页]

作者: 曹佳佳    时间: 2013-1-11 09:06
标题: 麻烦各位帮我详细解释下这个代码?
本帖最后由 张向辉 于 2013-1-16 12:27 编辑

FileInputStream fis = null;
        try {
            fis = new FileInputStream("F:\\a.txt");
            int temp;
            String str = "";
            while((temp = fis.read()) != -1) {
                str += (char)temp;
            }            
            System.out.println(str);
            //将数字等正常输出
            System.out.println(new String(str.getBytes("ISO8859-1")));
        }
catch (FileNotFoundException e) {

            e.printStackTrace();
        }
catch (IOException e) {

            e.printStackTrace();
        }
finally {

            try {
                fis.close();
                fis = null;
            }
catch (IOException e) {

                e.printStackTrace();
            }
        }
a.txt中为汉字,以字节流读入,最后打印为正常汉字,请详细解释下上面注释部分,我想知道原理。谢谢



作者: 张云杰    时间: 2013-1-11 23:13
本帖最后由 张云杰 于 2013-1-11 23:18 编辑

跟你的转换有关,   System.out.println(new String(str.getBytes("ISO8859-1")))  这里应该是把你读取上来的文字 转换成 ISO8859-1 编码  然后, 把你所读取上来的byte 转换成 String 输出..  String 字符串啊, 字符串当然能输出汉字了..
个人不推荐 ISO8859-1 编码  建议UTF-8 , 然后做Text 文字获取的话, 最好是用字符流..
作者: 胡勇敏    时间: 2013-1-11 23:35
教你个办法,当你不明白某个方法是什么意思的时候,你应该首先想到是API文档。在这行代码中你应该查的是String的getBytes(Charset charset)方法。API中的解释是: 使用给定的 charset 将此 String 编码到 byte 序列,并将结果存储到新的 byte 数组。 不太明白什么意思是吧。那看看要传递的参数Charset是个什么东东呢,继续点Charset,你会在Charset的描述中找到ISO-8859-1  ,这时候你就应该能明白了原来这个ISO-8859-1 是一个编码表。继续往下就会发现这样的描述:编码字符集 是抽象字符集合和整数集合之间的映射关系。US-ASCII、ISO 8859-1、JIS X 0201 和与 ISO 10646-1 相同的完整 Unicode 都是编码字符集示例。所以说ISO-8859-1是一种映射关系。到这里应该就能明白了这段代码str.getBytes("ISO8859-1")的意思就是参照ISO8859-1编码表返回一个byte[]型数组。而继续查API看String的构造函数 你会发现有个这样的构造函数String(byte[] bytes),而我们这句正好用的就是这个构造函数,而他的描述是:通过使用平台的默认字符集解码指定的 byte 数组,构造一个新的 String,原来他也是参照的编码表,所以通过编码表映射返回的byte构建的字符就能正确的显示出来了。  我看你帖子的时候也完全不知道那句话的意思,我是通过查API得到的以上步骤,你不知道对你有没有启示。
作者: 肖志锋    时间: 2013-1-11 23:40
前面的和后面那些我就不解释了,我就解释下下面这段吧 ,希望对你有帮助:
//第一句,不用说了,你懂得一个输入流,读文件
fis = new FileInputStream("F:\\a.txt");
//定义两个零时变量,一个temp接收每次读取的字节,而str则是把接受所有字节
            int temp;
            String str = "";
//这句你懂的...
            while((temp = fis.read()) != -1) {
//这句也简单,把32位的Int变成16位字符嘛,其实就是把int的前2个八位去掉,因为前面那一步把前16位补齐了,然后str接收。
                str += (char)temp;
            }
//这句我想你肯定懂的是乱码,你懂的         
  
            System.out.println(str);
            //将数字等正常输出
            System.out.println(new String(str.getBytes("ISO8859-1")));
这一句当然就是重点了,我们一句句一层层解释:
1:str.getBytes("ISO8859-1"):将前面获得str字符串,按照ISO8859-1的编码方式变成字节数组。这是jdk1.6的新特性。
2:new String(....):将字节数组通过构造函数重新变成字符串。
这些都好理解,也简单,我想最难理解的应该就是为什么使用ISO8859-1就可以,使用其他的编码方式都不行。
其实这跟ISO8859-1的编码方式有关这个是主要原因,先说我们的汉字是两个字节来表示的这个没问题吧?低位字节和高位字节,但是呢,当你把他们拆开的时候就变成两个字节了。
ISO8859-1是8位的编码也就是使用的了单个字节的所有位数,不像ASCII之类的是7位的,这样在传输中能接收字节内的所有数据,而不会因为把最高位当成符号而丢失数据了。
把前面变成字符的时候保留下来的8位数据完全的接收了,因此不会缺少数据,显示也就正确了。当然这只是我的了解而已,再深入的我也不是很清楚了。







欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2