前言
Java 中的“流”是一种抽象的概念,也是一种比喻,就好比水流一样,水流是从一端流向另一端的,而在 Java 中的“水流”就是数据,数据会从一端“流向”另一端。
根据流的方向性,我们可以将流分为输入流和输出流,当程序需要从数据源中读入数据的时候就会开启一个输入流,相反,写出数据到某个数据源目的地的时候也会开启一个输出流,数据源可以是文件、内存或者网络等。
1.什么是字节流?
字节流的基本单位为字节(Byte),一个字节通常为 8 位,它是用来处理二进制(数据)的。字节流有两个基类:InputStream(输入字节流)和 OutputStream(输出字节流)。
常用字节流的继承关系图如下图所示:
其中 InputStream 用于读操作,而 OutputStream 用于写操作。
long start_time = System.currentTimeMillis();
File file = new File("D:/4/copy.pdf");
File fileOs = new File("D:/5/copy.pdf");
FileInputStream fis =null;
FileOutputStream fos = null;
try {
fis = new FileInputStream(file);
fos = new FileOutputStream(fileOs);
int len;
while((len = fis.read())!=-1){
fos.write(len);
}
}catch (Exception e){
e.printStackTrace();
}finally {
if (fis!=null){
fis.close();
}
if (fos!=null){
fos.close();
}
}
long end_time = System.currentTimeMillis();
System.out.println("该任务耗时:"+(end_time-start_time)+"毫秒");
一个字节一个字节传送
结果是该任务耗时:3997毫秒
long start_time = System.currentTimeMillis();
File file = new File("D:/4/copy.pdf");
File fileOs = new File("D:/5/copy.pdf");
FileInputStream fis =null;
FileOutputStream fos = null;
try {
fis = new FileInputStream(file);
fos = new FileOutputStream(fileOs);
byte[] bytes = new byte[fis.available()];
while((fis.read(bytes))!=-1){
fos.write(bytes);
}
}catch (Exception e){
e.printStackTrace();
}finally {
if(fis!=null){
fis.close();
}
if(fos!=null){
fos.close();
}
}
long end_time = System.currentTimeMillis();
System.out.println("该任务耗时:"+(end_time-start_time)+"毫秒");
字节数组拷贝之available()方法,通过fis.available()获取所有字节,一次写入。弊端:有可能会内存溢出。
结果是该任务耗时:35毫秒
long start_time = System.currentTimeMillis();
File file = new File("D:/4/copy.pdf");
File fileOs = new File("D:/5/copy.pdf");
FileInputStream fis =null;
FileOutputStream fos = null;
try {
fis = new FileInputStream(file);
fos = new FileOutputStream(fileOs);
int len;
byte[] bytes = new byte[1024 * 8];
while((len=fis.read(bytes))!=-1){
fos.write(bytes,0,len);
}
}catch (Exception e){
e.printStackTrace();
}finally {
if(fis!=null){
fis.close();
}
if(fos!=null){
fos.close();
}
}
long end_time = System.currentTimeMillis();
System.out.println("该任务耗时:"+(end_time-start_time)+"毫秒");
定义小数组的标准格式
E:小数组的读写和带Buffered的读取哪个更快?
定义小数组如果是8192个字节大小和Buffered比较的话
定义小数组会略胜一筹,因为读和写操作的是同一个数组
而Buffered操作的是两个数组
flush和close方法的区别:
flush()方法
用来刷新缓冲区的,刷新后可以再次写出
close()方法
用来关闭流释放资源的,如果是带缓冲区的流对象的close()方法,不但会关闭流,还会在关闭流之前刷新缓冲区,关闭后不能再写出
结果是该任务耗时:79毫秒
long start_time = System.currentTimeMillis();
File file = new File("D:/4/copy.pdf");
File fileOs = new File("D:/5/copy.pdf");
FileInputStream fis =null;
FileOutputStream fos = null;
BufferedInputStream b_fis = null;
BufferedOutputStream b_fos = null;
try {
fis = new FileInputStream(file);
fos = new FileOutputStream(fileOs);
b_fis = new BufferedInputStream(fis);
b_fos = new BufferedOutputStream(fos);
int len;
while((len=b_fis.read())!=-1){
b_fos.write(len);
//b_fos.write(len); 先把字节写到内存中(也就是Buffered缓冲数组中)当把
//缓冲数组填满后再一次性写到磁盘中去。
//关于缓冲区的解释,毕老师视频中有一个比喻的,假如楼主一顿饭要吃5个包子,而包子是在厨房,楼主
//又比较喜欢在书房边看java边吃饭,这个时候就可以拿碗,把5个包子装一个碗中,
//这样楼主只需要跑一次厨房了,
//没有碗的话,楼主需要跑5次厨房.我的理解,碗应该就是缓冲区的意思了.
}
b_fos.flush();
}catch (Exception e){
e.printStackTrace();
}finally {
if (b_fis!=null){
b_fis.close();
}
if (b_fos!=null){
b_fos.close();
}
if(fis!=null){
fis.close();
}
if(fos!=null){
fos.close();
}
}
long end_time = System.currentTimeMillis();
System.out.println("该任务耗时:"+(end_time-start_time)+"毫秒");
BufferedInputStream和BufferOutputStream拷贝,缓冲思想。
结果是该任务耗时:79毫秒