当前位置: 首页 > 后端技术 > Java

java培训关闭流方法有顺序吗

时间:2023-04-01 22:10:38 Java

是否有java培训关闭流方法的命令?通常我们把输入流和输出流用buffer包裹起来,看看下面的代码(这段代码运行正常,不会报错)importjava.io.BufferedOutputStream;importjava.io.FileOutputStream;importjava.io.IO异常;公共类IOTest{publicstaticvoidmain(String[]args)throwsIOException{FileOutputStreamfileOutputStream=newFileOutputStream("c:\a.txt");BufferedOutputStreambufferedOutputStream=newBufferedOutputStream(fileOutputStreameswput.outritew"buffered".getBytes());bufferedOutputStream.flush();//从wrapperstreambufferedOutputStream.close();}}中关闭流该方法是否调用fileOutputStream。关闭();先看BufferedOutputStream的源码:publicclassBufferedOutputStreamextendsFilterOutputStream{...可以看到它继承了FilterOutputStream,并没有重写close方法,所以直接看FilterOutputStream的源码:publicvoidclose()throwsIOException{try{flush();}catch(IOExceptionignored){}out.close();}trackout(inFilterOutputStream):protectedOutputStreamout;publicFilterOutputStream(OutputStreamout){this.out=out;}再看看BufferedOutputStream:if(size<=0){thrownewIllegalArgumentException("Buffersize<=0");}buf=newbyte[size];}可以看到BufferedOutputStream调用了super(out);即out.close();调用的是通过BufferedOutputStream传入的wrappedstream,这里是FileOutputStream_java训练我们在看其他类似的,比如BufferedWriter的源码:publicvoidclose()throwsIOException{synchronized(lock){if(out==null){return;}try{flushBuffer();}finally{out.close();out=null;cb=null;}}}通过观察各种流的源码,可以得出wrappedstreams会自动调用包装流的关闭方法,而无需自己调用。是否有关闭流方法的命令?从上面的结论,产生一个问题:如果wrappedstream被手动关闭会怎么样,关闭stream有没有顺序?事实上,我们习惯于关闭两个流。首先,让我们做一个简单的实验。在第一题代码的基础上,添加手动增加关闭流的代码,那么有两个命令:1.先关闭wrappedstream(一般不会抛出异常)importjava.io.BufferedOutputStream;importjava.io.FileOutputStream;导入java.io.IOException;公共类IOTestBufferedOutputStreambufferedOutputStream=newBufferedOutputStream(fileOutputStream);bufferedOutputStream.write("testwritesomething".getBytes());bufferedOutputStream.flush();fileOutputStream.close();//先关闭wrappedstreambufferedOutput(Stream)ream}.}2。首先关闭包装流(通常不会抛出异常)FileOutputStreamfileOutputStream=newFileOutputStream("c:\a.txt");BufferedOutputStreambufferedOutputStream=newBufferedOutputStream(fileOutputStream);bufferedOutputStream.write("测试写东西".getBytes());bufferedOutputStream.flush();bufferedOutputStream.close();//先关闭包流fileOutputStream.close();}}上面两种写法都可以,我们已经知道bufferedOutputStream.close();会自动调用fileOutputStream。关闭();方法,那么这个方法是如何执行的呢?我们看一下FileOutputStream的源码:publicvoidclose()throwsIOException{synchronized(closeLock){if(closed){return;}closed=true;}...可以看出它使用了同步锁,使用aclosemark,如果已经关闭,则不会再操作,所以多次调用不会有问题如果没有看过参考文章,我可能会得出一个结论,关闭流不需要考虑顺序。我们看下面的代码(参考文章修改):(String[]args)throwsIOException{FileOutputStreamfos=newFileOutputStream("c:\a.txt");OutputStreamWriterosw=newOutputStreamWriter(fos,"UTF-8");BufferedWriterbw=newBufferedWriter(osw);bw.write("javaIOclosetest");//从innerband到outer的序列会报异常fos.close();osw.close();bw.close();}}将抛出StreamclosedIO异常:线程“main”中的异常java.io.IOException:Streamclosedatsun.nio.cs.StreamEncoder.ensureOpen(StreamEncoder.java:45)atsun.nio.cs.StreamEncoder.write(StreamEncoder.java:118)atjava.io.OutputStreamWriter.write(OutputStreamWriter.java:207)atjava.io.BufferedWriter.flushBuffer(BufferedWriter.java:129)atjava.io.BufferedWriter.close(BufferedWriter.java:264)在IOTest.main(IOTest.java:18)和ifbw.close();先放,其他顺序随意,即修改成下面两个:bw.close();操作系统w.close();fos.close();bw.close();fos.close();osw.close();不会报错,这是为什么呢,我们来看看BufferedWriter的close源码:publicvoidclose()throwsIOException{synchronized(lock){if(out==null){return;}try{flushBuffer();}finally{out.close();out=null;cb=null;}}}里面调用了flushBuffer()方法,也是抛出异常的错误方法:voidflushBuffer()throwsIOException{synchronized(lock){ensureOpen();if(nextChar==0)return;out.write(cb,0,nextChar);nextChar=0;}}可以看到一大行out.write(cb,0,nextChar);如果在流关闭后执行此行,则会抛出IO异常。有时候我们会这样写:fos.close();fos=null;osw.close();osw=null;bw.close();bw=null;这样也会抛出异常,但是是ensureOpen()抛出的在flushBuffer()中,从源码可以看出:){ensureOpen();if(nextChar==0)return;out.write(cb,0,nextChar);nextChar=0;}}如何防止这种情况?只需编写以下形式:bw.close();bw=空;结论:流上的close方法可以多次调用。理论上不需要考虑关闭流的顺序,但是有时候在close方法中调用write等待method_java训练机时会抛出异常基于以上两个结论,可以得出以下建议:关闭一个流,只需要关闭最外层的wrapperstream,其他流会自动调用close,保证不会抛出异常。如:bw.close();//下面三个无序osw=null;fos=null;bw=null;注意,在某些方法中,close方法除了wrappedstream的close方法外,还会调用wrappedstream,将其设置为null,方便JVM回收。在bw.close()中:publicvoidclose()throwsIOException{synchronized(lock){if(out==null){return;}try{flushBuffer();}finally{out.close();out=null;cb=null;}}}终于有了设置为null的代码,所以有时候不需要手动设置为null。(个人建议是记下来,执行时间不多)