欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Java IO 初探

程序员文章站 2022-06-01 23:51:17
...

       这段时间,在给公司的一批新员工培训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有了更深入的认识。从而也映证了我的观点:通过给别人培训,可以大大加深你对这块知识的应用与理解,这对自学是非常有用的。