- JAVA中的流分为两种:字节流和字符流。与字节流相对应的抽象类是InputSteam和OutputStream;与字符流相对应的抽象类是Reader和Writter。JAVA中其它各种各样的I/O类都是由这四个抽象类派生出来的。
- 字符流和字节流的区别在于,字符流操作的对象是字符及字符数组,而字节流操作的对象则是字节及字节数组。看看字节流的类图,还有它们的使用方法:
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class Main {
public static void main( String []args ){
File source = new File( "/home/ziyao/下载/source.tar.gz");
File dest = new File( "/home/ziyao/下载/dest.tar.gz" );
FileInputStream fin = null;
FileOutputStream fout = null;
try{
//使用File类对象作为构造参数
fin = new FileInputStream( source );
fout = new FileOutputStream( dest );
byte[] buffer = new byte[1024];
int readNum = 0;
long time = System.currentTimeMillis();
while( (readNum = fin.read( buffer,0,buffer.length ))!=-1 ){
fout.write( buffer, 0, readNum );
}
time = System.currentTimeMillis()-time;
//total time used: 2159
System.out.println( "total time used: " + time );
//使用文件路径作为构造参数
FileInputStream fi = new FileInputStream("/home/ziyao/下载/source.tar.gz");
FileOutputStream fo = new FileOutputStream( "/home/ziyao/下载/dest2.tar.gz");
BufferedInputStream bin = new BufferedInputStream( fi );
BufferedOutputStream bout = new BufferedOutputStream( fo );
time = System.currentTimeMillis();
while( (readNum = bin.read( buffer,0,buffer.length ))!=-1 ){
bout.write( buffer, 0, readNum );
}
time = System.currentTimeMillis()-time;
//total time used: 1545
System.out.println( "total time used: " + time );
}catch( Exception e ){
e.printStackTrace();
}finally{
try {
fin.close();
fout.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
从上面的例子可以看出,BufferedInputStream加BufferedOutputStream的使用比FileInputStream加FileOutputStream的使用效率高很多!为什么呢?
我们去查看JDK的源代码会发现,BufferedInputStream和BufferedOutputStream分别继承了相应的InputStream和OutputStream,同时,BufferedInputStream内部有一个InputStream变量,BufferedOutputStream有一个OutputStream变量,而BufferedInputStream中的读操作是由InputStream完成的,BufferedOutputStream的写操作是由OutputStream完成的。根据我们的例子:
bin = new BufferedInputStream( fi );
bout = new BufferedOutputStream( fo );
所以,真正在流里执行读写的还是FileInputStream和FileOutputStream,但是为什么会导致所花的时间不一样呢?原因就是BufferedInputStream和BufferedOutputStream内部都维持一个byte数组,这个数组用于存储缓存,就是:
读的时候,BufferedInputStream一次让FileInputStream从流里读大量数据存储在byte数组中,然后调用者要读的时候只要从byte数组中拿数据就可以了,当byte数组满了,再从流里大量读取数据到byte数组中。byte数组是在内存里的,所以比在流里读取的速度要快很多;
写的时候,BufferedOutputStream把要写的数据放在byte数组中,然后当byte数组满的时候,让FileOutputStream把byte数组里的数据写到流里。
综上所述,BufferedInputStream和BufferedOutputStream就是通过减少在流里的读写操作来提高性能的。