日期:2014-05-20  浏览次数:21010 次

关于Io流的close的问题
本帖最后由 u010010338 于 2013-09-02 01:09:54 编辑
import java.io.*;
public class TestTransForm1 {
public static void main(String[] args) {
try {
OutputStreamWriter osw = new OutputStreamWriter(new    FileOutputStream("D:/java/io/TestTransForm.txt"));
osw.write("abc");
System.out.println(osw.getEncoding());
osw.close();    //最后结果是写入abcdef,如果没有这句,最后结果写入def,求解析,分析下内存
osw = new OutputStreamWriter(new FileOutputStream("D:/java/io/TestTransForm.txt",true),"ISO8859_1");
osw.write("def");
System.out.println(osw.getEncoding());
osw.close();
} catch (IOException ex) {ex.printStackTrace();}
}
}
io流

------解决方案--------------------
输出流有缓冲区,原则是数据先输入到缓冲区,缓冲区满了才输出。关闭前需要清空flush一下缓冲区(这是习惯),不然缓冲区里最后剩下的数据就没了。
你这里可以在osw.close();加一句osw.flush();就不会只有def的情况了。
至于你说的close()是因为close()方法会调用flush(),所以才会出现你说的情况。
不过具体缓冲区是啥,close()怎么调用的flush()俺也不清楚。
查了下api,发现原来是Outputstreamwriter 里的StreamEncoder自带一个ByteBuffer字节缓冲区。close()方法会先清空这个缓冲区再关闭流。现在清楚了吧
好人做到底。。。这是StreamEncoder的源码
http://www.docjar.com/html/api/sun/nio/cs/StreamEncoder.java.html
PS:输入输出流每次用完一定得关掉,不然它占资源,还不报错。到时会死的很惨。。。一般把close放在finally里。

------解决方案--------------------
osw调用write()方法是将字符串保存到缓冲区中,当你关闭资源时调用close()方法之前,会自动调用一次flush()方法,此方法会将缓冲区中的字符串一次性发送到文件中,然而你又创建了一个新的OutputStreamWriter对象,还是往同一个文件中写字符串,因为第二个参数是true,表示追加操作,所以当你第二次调用close()方法时,又会将缓冲区的字符串"def"一次性写入文件中,此次写入是追加不是覆盖,所以最终你的结果是abcdef,如果没有第一个close()方法,则第一次要写入的字符串"abc"会一直保存在缓冲区中,因为你没有调用flush()方法,你又将引用指向新创建的第二个OutputStreamWrtier对象,再往同一个文件中写入字符串,最后调用close()方法,会调用flush()将"def"写入文件,而abc则一直保存在缓冲区中,没有写入成功!