Java的I/O,按照数据传输单位大小可以分为字符流和字节流。字符流名副其实,每次仅仅传输一个字符。字节流,每次传输8bits一个字符。 他们通过与文件建立管道进行连接。每次分别传输一个字符或着字节。 这样,在小批量处理数据中,看不出什么效果,如果数据惊人,就会效率低下。并且对频繁读写硬盘,减少硬盘使用寿命。
字节流Stream
java语言中字符流都有共性是方法名有Stream 他们都继承了InputStream 和OutPutStream 两个抽象类并实现其中的抽象方法(常用的Read方法和Close方法)。下面以InputStream为例。 每一个inputStream 都有与之相对应的OutputStream
//通过字节流将一个文本a.txt复制到另一个文档b.txt里面去import java.io.*;public class TestCopyTXT { public void CopyByStream()throws Exception { FileInputStream fis=new FileInputStream("a.txt");//注意这个FileInputStream 在构造的时候,如果没有发现a.txt文件,他判处找不到文件的异常FileNotFoundException FileOutputStream fos=new FileOutputStream("b.txt",true);//这个对象如果在创建的时候 没有发现b.txt的话,会自动创建,而且后面有可选参数布尔值。表面是否可以添加,还是重新覆盖填写。此处为在最后添加。 int b=0; while((b=fis.read())!=-1){ fos.write(b); //如果要打印输出的话,则必须把字节数强制类型转换成char型的。 //System.out.print((char)b); 此处如果输出有中文的话,则会出现乱码。 } fis.close();// 流使用过后要记得关闭。 fos.flush(); fos.close(); }}
以上就是字节流的打印方法。但是如果sysout输出中文的话,会出现???。因为中文是两个字节,所以会出现乱码。要解决这个输出的问题,就必须采用字符流。字符流的类关系示意图如下,每个Reader也都分别对应的Writer
//和上段代码实现一样的过程 用Reader来实现这个过程。import java.io.*;public class TestCopyTxt{ public void CopyByReader() throws Exception{ FileReader fr=new FileReader("a.txt"); FileWriter fw=new FileWrite("b.txt",true);//可以发现他们和字节流的处理过程,和方法名称是一样一样的。 int b=0; while((b=fr.read())!=-1){ System.out.print((char)b); fw.write(b); } fr.close(); fw.flush(); fw.close(); }}
通过以上两个例子可以看出来java中 字节流和字符流处理流程是一模一样的,和方法名都是一模一样的,只不过一个是以字节为单位8bit 一个是以字符为单位的16bit。在使用的时候建议是采用字符流,兼容性好些。
但是如果不论是字节流还是字符流,都是数以节点流。这些流每次从硬盘上都是读取一个基本数据单位。如果长时间使用势必造成效率的低效和系统资源的浪费。因此我们在此,考虑使用缓冲队列。来降低硬盘读写带来
的压力。因此我们在此考虑用缓冲来解决这个问题。如下图所示:
这也叫处理流。与节点流最大不同就是处理的是批量的数据。可以更灵活。可以指定缓冲区大小,但默认已经足够大了。
public class TestBuffered{ public void ReadTxt() throws Exception{ FileReader fr=new FileReader("a.txt"); BufferedFileReader bfr=new BufferedFileReader(fr); String s; while((s=bfr.readLine())!=null){ //readLine 方法返回的是当前读取到的字符串,并不是一切的字节了。 System.out.println(s); } fr.close(); //由内到外进行关闭,先将内管道关闭后。然后在关闭外缓冲 bfr.close(); }}
由上面的例子可以看到java中的处理流把节点流的基础上封装了一层Buffered。这样再访问的时候,使得访问效率更加高,每次访问硬盘的数据更多。使访问效率得到提升,需要注意的是BufferedReader中和BufferedWriter中几个方法
最后一点就是字节流输入向字符输入流的转化过程。
@Test public void TransformRead() throws Exception { //通过把FileInputStream封装起来放入FileInputStreamReader中,完成转换字符流,最后使用buffered方法输出,其中StreamReader后面可以跟上编码格式。 InputStreamReader a=new InputStreamReader(new FileInputStream("G:/JavaTest/练习代码/PrintUnicode.java"),"gbk"); BufferedReader br=new BufferedReader(a); String s; while((s=br.readLine())!=null) { System.out.print(s); } a.close(); br.close(); }
上面的程序中对流进行了两次封装。第一次封装为转换流的格式。第二次封装改变流处理的方式。因此如下图所示。采用处理流方式可以提高效率。并且更好的复合人机交互。