黑马程序员技术交流社区
标题:
IO中read方法的一个小问题<已解决,谢谢诸位>
[打印本页]
作者:
黑马-王建雨
时间:
2012-5-12 07:58
标题:
IO中read方法的一个小问题<已解决,谢谢诸位>
本帖最后由 啷个里个郞 于 2012-5-12 10:52 编辑
package cn.itcast.day01;
import java.io.*;
public class O {
static class ReflectTest {
public static void main(String[] args) throws IOException
{
FileWriter fw = new FileWriter("123.txt");
fw.write("abcdefg");
fw.close();
FileReader fr = new FileReader("123.txt");
System.out.println((char)fr.read());
System.out.println((char)fr.read());
System.out.println((char)fr.read());
fr.close();
System.out.println((char)fr.read());
//不明白的是为什么连最后一条语句都会读取出来,上面语句不是关闭此流资源了吗?
}
}
}
作者:
小小企鹅
时间:
2012-5-12 08:29
close()关闭该流并释放资源,关闭后再调用read()将抛出IOException
作者:
—__
时间:
2012-5-12 08:39
close()关闭该流并释放资源,同时会在刷新一次,所以 fr.close(); 后的一句 System.out.println((char)fr.read()); 会被打印。
同时如果你在 后面在添加一句 System.out.println((char)fr.read()); 的话 就会报异常信息了
作者:
永恒之翼网络
时间:
2012-5-12 08:58
原因是字符流是对字节流的包装。它里面多了个缓存,缓存很小只有两个byte(因为char有两个byte),而英文字母却只用了一个byte的,编译系统默认的是UTF-8的,允许Unicode码在硬盘文件存取字母时用一个byte。第一次调用read方法时,字符流会从文件中读取两个byte,并存放在缓存中,然后把第一个byte转换成int返回;第二次调用read方法时,会直接到缓存中找,返回第二个byte。第三次时,会再文件中读取两个byte,返回第一个byte。以此类推,第四次调用read方法时,就算关了流,read方法回到内存中找,而不是去文件中找。所以上面的代码运行没有出错。如果再加一行 “System.out.println((char)fr.read()); ”就会出错。
static class ReflectTest {
public static void main(String[] args) throws IOException
{
FileWriter fw = new FileWriter("123.txt");
fw.write("abcdefg");
fw.close();
FileReader fr = new FileReader("123.txt");
System.out.println((char)fr.read());
System.out.println((char)fr.read());
System.out.println((char)fr.read());
fr.close();
// System.out.println((char)fr.read());
System.out.println((char)fr.read()); //不明白的是为什么连最后一条语句都会读取出来,上面语句不是关闭此流资源了吗?
}
}
}
作者:
刘亚超
时间:
2012-5-12 09:04
这个问题问的好,之前我也没有注意过,按理说,楼主的代码应该会抛异常的,但事实上却没有,原因为:
fr.read()方法,查源码会发现,他最终是调用 StreamDecoder 类的read0 方法,
36 public class StreamDecoder extends Reader
37 {
....
111 public int read() throws IOException {
112 return read0();
113 }
114
115 private int read0() throws IOException {
116 synchronized (lock) {
117
118 // Return the leftover char, if there is one
119 if (haveLeftoverChar) {
120 haveLeftoverChar = false;
121 return leftoverChar;
122 }
123
124 // Convert more bytes
125 char cb[] = new char[2];
126 int n = read(cb, 0, 2);
127 switch (n) {
128 case -1:
129 return -1;
130 case 2:
131 leftoverChar = cb[1];
132 haveLeftoverChar = true;
133 // FALL THROUGH
134 case 1:
135 return cb[0];
136 default:
137 assert false : n;
138 return -1;
139 }
140 }
141 }
从 125-126行可以看出,read方法,其实是是每次read 2个字符,但只返回了一个,再次调用read方法时,其实并没有读文件,而是将缓存中的字符返回给用户了。
楼主的代码在fr.close()之前调用了三次read 此时还有一个字符在缓存中,第4次调用read方法时,并没有真的去读文件,所以没有抛异常,如果楼主的代码,再多读一次read方法,就会抛异常了。
作者:
张晨
时间:
2012-5-12 10:01
本帖最后由 张晨 于 2012-5-12 10:02 编辑
这是一个小BUG,本意是为了效率多读一个char。也就是说只要有可能read()就读两个字符(就是上面代码中read(cb, 0, 2)),一个输出一个放缓存,如果第二次调用read()方法,他会直接调用缓存缓存,而不会调用更加底层的implRead(cbuf, off, off + len),而后把缓存置为空。 所以也就不会检测此流是否已经被关闭了!
楼主代码在第二次read()的时候,close(),然后在read()是会抛出异常的。{:soso_e100:}
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/)
黑马程序员IT技术论坛 X3.2