Java IO 初探
这段时间,在给公司的一批新员工培训Java IO的过程中,重新对自己之前学的Java IO有了新的认识。
先从一段代码说起:如下:
import java.io.ByteArrayInputStream; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.SequenceInputStream; import java.util.ArrayList; import java.util.Collections; import java.util.Enumeration; import java.util.List;
public class SequenceStreamTest {
/** * @throws Exception * @功能 顺序输入流测试 // */ public static void main(String[] args) throws Exception { FileInputStream fis_01 = new FileInputStream("D:\\Java IO\\测试数据\\error.txt"); ByteArrayInputStream byis = new ByteArrayInputStream("德邦信息技术中心欢迎您".getBytes("GBK")); FileInputStream fis_02 = new FileInputStream("D:\\Java IO\\测试数据\\清查明细.txt"); List arrayList = new ArrayList(); arrayList.add(fis_01); arrayList.add(byis); arrayList.add(fis_02); Enumeration cocel = Collections.enumeration(arrayList); SequenceInputStream seq = new SequenceInputStream(cocel); byte[] buf = new byte[1024]; // int i= -1; int n=0; FileOutputStream fout = new FileOutputStream("D:\\Java IO\\测试数据\\seq.txt"); while((seq.read(buf))>0) { fout.write(buf); fout.flush(); } seq.close(); fout.close(); }
}
这段代码执行完成之后,我发现并不是我想要的结果。我的预期结果是,哪个流先加进去,就在结果文件中先出现它的内容。但是最后的结果是,第二个流的内容,在第一个流的内容里面,而且第一个流读取的内容有问题,出现了一些重复的内容。这个问题我在给新员工培训时,没有搞明白是什么问题。后来,课下,我思考了下,其实比较容易理解的。是这样的,对于同一个字节数组,从多个流读取数据,对每一个流的最后一次读取,并不一定能够装满这个字节数组,而没有装满这个数组的那部分内容,就是上一次读取的内容,就会出现内容重复及不同流的内容相互交叉的情况。所以,重点是要修改以下代码段:
int n=0; FileOutputStream fout = new FileOutputStream("D:\\Java IO\\测试数据\\seq.txt"); while((n=seq.read(buf))>0) { fout.write(buf,0,n); fout.flush(); }
接下来,又遇到一个问题:那就是教程里面说PrintStream这个类,在设置其自动刷新缓冲区后,只要调用println()即可自动把数据写到数据汇中,反之,就是如果不设置自动刷新,那么,调用println()就不会自动把数据写到数据汇中,但是接下来这段代码却出现了一些奇怪的现象:
import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.DataInputStream; import java.io.FileOutputStream; import java.io.PrintStream; import java.math.BigDecimal; public class PrintStreamTest { /** * @throws Exception * @功能 PrintStream测试 */ public static void main(String[] args) throws Exception { FileOutputStream fout = new FileOutputStream("H:\\常春藤培训\\韩旺坤\\Java IO\\测试数据\\ps.txt"); fout.write("hanwangkunxx".getBytes()); PrintStream ps = new PrintStream(fout,false); ps.print("2012年常春藤培训正式开始!"); ps.println("德邦信息技术中心欢迎大家加入这个大家庭!"); ps.println("2012年国庆中秋连续放假8天!"); ps.close(); } }
这段代码,按上面教程的理解,那么应该是:在每次调用println()后,不应该会把数据写到数据汇中,但是实际结果是每次调用之后都会把结果写到数据汇当中,这也是在课堂上未解决的问题。后来,在课下,我查看了源码及网上有关资料,发现是因为这样的:上面那条规则只是对有缓冲区的流才适用的,而我们的FileOutputStream及PrintStream都是没有缓冲区的,所以对这条规则是不适用的,所以如果换成下面的代码就可以了:
import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.DataInputStream; import java.io.FileOutputStream; import java.io.PrintStream; import java.math.BigDecimal; public class PrintStreamTest { /** * @throws Exception * @功能 PrintStream测试 */ public static void main(String[] args) throws Exception { FileOutputStream fout = new FileOutputStream("D:\\Java IO\\测试数据\\ps.txt"); fout.write("hanwangkunxx".getBytes()); PrintStream ps = new PrintStream(new BufferedOutputStream(fout),true); ps.print("2012年常春藤培训正式开始!"); ps.println("德邦信息技术中心欢迎大家加入这个大家庭!"); ps.println("2012年国庆中秋连续放假8天!"); ps.close(); } }
从这个问题,我突然又发现了,不是说输出流只有在调用flush()方法或close()才会把数据写到数据汇中吗?但是第二个例子,却不是这样的。我查看了OutputStream及FileOutputStream两个流的源代码,发现对于OutputStream类,它的flush()方法是个空的方法,不做任何方法,而FileOutputStream并没有重写OutputStream的flush()方法,所以他们调用的是同一个方法,也就是说对于FileOutputStream流类,有没有调用flush()
方法,它都会把立即把数据写到数据汇中,再仔细一看FileOutputStream的write()方法,发现其是调用底层写的DLL文件来进行数据写操作的。
此时,我又想起之前的一个问题,就是有些流的:markSupported()方法返回true,而有些返回false。经过查看源码,发现不仅这个方法,reset()和mark()方法都是针对有缓冲区的流来说的,对于有缓冲区的流这些方法都是
可以用的,使用这些方法对相应的数据源进行重复读写操作。
至此,通过培训的几个问题,我对Java IO有了更深入的认识。从而也映证了我的观点:通过给别人培训,可以大大加深你对这块知识的应用与理解,这对自学是非常有用的。
下一篇: 差分法求数据压缩