关于复制文件的一二三
RandomAccessFile
首先是第一种,RandomAccessFile是Java中输入,输出流体系中功能最丰富的文件内容访问类,它提供很多方法来操作文件,包括读写支持,与普通的IO流相比,它最大的特别之处就是支持任意访问的方式,程序可以直接跳到任意地方来读写数据。但要注意的是RandomAccessFile是不属于InputStream和OutputStream类系,它是一个直接继承Object的,独立的类。
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
public class CopyDemo1 {
public static void main(String[] args) throws IOException {
RandomAccessFile src =new RandomAccessFile("music.mp3", "r");
RandomAccessFile desc = new RandomAccessFile("copy_music.mp3", "rw");
int d = -1;
long start = System.currentTimeMillis();
while ((d=src.read())!=-1) {
desc.write(d);
}
long end = System.currentTimeMillis();
System.out.println("复制耗时:"+(end-start)+"ms");
src.close();
desc.close();
}
}
运行结果:
复制耗时:23156ms
很显然,这种复制效率低,原因是一次读取的数据少导致硬盘频繁读写想要提高读写效率,就要提高读写的数据量,减少读写次数从而提供读写效率。
字节流
字节流的操作效率就提升很多
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class CopyDemo2 {
public static void main(String[] args) throws IOException {
FileInputStream src = new FileInputStream("music.mp3");
FileOutputStream desc = new FileOutputStream("Copy_music.mp3");
byte[] datas = new byte[1024*10];
int len = -1;
long start = System.currentTimeMillis();
while ((len = src.read(datas)) != -1) {
desc.write(datas,0,len);
}
long end = System.currentTimeMillis();
System.out.println("复制完成!,耗时:"+(end-start)+"ms");
src.close();
desc.close();
}
}
运行结果:
复制完成!,耗时:14ms
文件字节流:一切文件在系统中都是以字节的形式保存的,无论你是文档文件、视频文件、音频文件...,需要读取这些文件都可以用FileInputStream去读取其保存在存储介质(磁盘等)上的字节序列。FileInputStream在创建时通过把文件名作为构造参数连接到该文件的字节内容,建立起字节流传输通道。然后通过 read()、read(byte[])、read(byte[],int begin,int len) 三种方法从字节流中读取 一个字节、一组字节。
缓冲流
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class CopyDemo3 {
public static void main(String[] args) throws IOException {
FileInputStream src = new FileInputStream("music.mp3");
BufferedInputStream bis = new BufferedInputStream(src);
FileOutputStream desc = new FileOutputStream("music_copy.mp3");
BufferedOutputStream bos = new BufferedOutputStream(desc);
byte[] datas = new byte[1024];
int len = -1;
long start = System.currentTimeMillis();
while ((len = bis.read(datas))!=-1) {
bos.write(datas,0,len);
}
long end = System.currentTimeMillis();
System.out.println("复制完成!耗时:"+(end-start)+"ms");
bis.close();
bos.close();
}
}
运行结果:
复制完成!耗时:11ms
带缓冲的字节流:上面我们知道文件字节输入流的读取时,是直接同字节流中读取的。由于字节流是与硬件(存储介质)进行的读取,所以速度较慢。而CPU需要使用数据时通过read()、read(byte[])读取数据时就要受到硬件IO的慢速度限制。我们又知道,CPU与内存发生的读写速度比硬件IO快10倍不止,所以优化读写的思路就有了:在内存中建立缓存区,先把存储介质中的字节读取到缓存区中。CPU需要数据时直接从缓冲区读就行了,缓冲区要足够大,在被读完后又触发fill()函数自动从存储介质的文件字节内容中读取字节存储到缓冲区数组。
区别
在FileInputStream里有一个说明是说此方法将阻塞,意思就是说在你读一个文件输入流的时候,当读到某个位置的时候,如果做一些其他处理(比如说接受一部分字节做一些处理等等)这个时候输入流在什么位置就是什么位置,不会继续往下读,而BufferedInputStream虽然也有一个read方法,但是从名字就可以看出,它带有一个缓冲区,它是一个非阻塞的方法,在你读到某个位置的时候,做一些处理的时候,输入流可能还会继续读入字节,这样就达到了缓冲的效果。