Java语言:这个缓冲流有点快(字节流总结)

目录

字节流

字节流概述

FileInputStream

FileOutputStream

缓冲流概述

BufferedInputStream

BufferedOutputStream

使用和缓冲流和不使用缓冲流的对比试验


字节流

字节流概述

要讲字节流

首先要明白什么是字节

字节其实就是010101,这样的二进制

小伙伴们都知道计算机的本质就是0101这样的二进制

所以在传输的过程中,其实是按照这个方式进行传输数据的

因此字节流可以理解为一条传输数据的河流

那么是什么样的河流呢?

是一条充满0101这样二进制的河流

 

字节流分为字节输入流和字节输出流

下面上两张图

上面用红色框框住的就是重点要讲的内容

对于对象的输入输出流会放在序列化和反序列化那一部分讲

这一部分不讲序列化和反序列化

 

FileInputStream

FileInputStream中文意思是文件输入流

自然而然它的意思就是从文件系统中获得输入字节

用于读取如图像和数据之类的原始字节流

类似于下面这样

下面介绍构造方法

一般情况下使用的构造方法是第一个或者是第三个构造方法

第一个构造方法的意思是使用File类的对象作为参数创建FileInputStream对象

第三个构造方法是直接将文件所在的路径作为参数创建一个FileInputStream对象

第二构造方法表示运用文件描述符创建输入流(文件描述符,至今还没有遇到过查了一下,没看懂,有大佬可以科普的吗?)

 

下面介绍FileInputStream中的常用方法

这里要解释的是第三个方法

第三个方法的意思是将读取之后的数据存放在字节数组b中,然后数组的长度为len,从索引为off的地方开始存储

第一个方法read中的返回值如果是-1,那么表示数据已经读取到了最后一个位置

第四个方法close,这个方法的使用就是在使用完字节输入流之后,记得要关闭字节输入流,因为IO的使用非常耗费资源

 

下面简单的使用字节输入流对文本中的数据进行读取,并打印出来

原文件是这样的

可以看到读取成功

 

还可以使用字节数组进行读取

或者这样

从b中的0号位置开始存储,存储5个字节

 

FileOutputStream

FileOutputStream从中文意思上来看就是文件输出流

文件输出流的作用就是将数据写入到文件中

下面介绍一下构造方法

 

 

常用的构造方法是第一个,就是使用File类的对象作为参数构造FileOutputStream对象实例

然后文件输出流默认是写入的数据会将文件中原来的数据进行覆盖

但是也可以通过时设置,不对原来的数据进行覆盖

那么就要用到第二个方法

第二个方法中的append参数设置成为true即可

这样就可以在原来的数据后面继续添加数据,而不是将数据进行覆盖

 

常用方法如下

其实你会发现这边的方法和FileInputStream中的方法似乎是对应好的

 

其实写到这里我会有一个疑问,对于同一个对象,多次调用write方法会不会对前面的数据进行覆盖

经过试验之后,发现不会,只有不同的对象对同一文件进行操作的时候,后面的数据会对前面的数据进行覆盖

 

下面看一个代码,就是对文件进行最基础的写操作

打开操作后的文件一看,不是我们写进去的内容,觉得错了

但其实这没有错,这是编码的问题,如果你对文件进行输出

你会发现输出的还是你写的那些内容

 

下面写一个对图片进行复制粘贴的程序

 

 

写完之后打开文件夹,你会发现是这样的,说明成功了

 

 

这里我还有一个疑惑就是对于FileOutputStream抛出的异常

开始看到居然会抛出一个文件找不到的异常,觉得很奇怪

,因为FileOutputStream创建对象的时候,如果文件不存在

,那么会自动创建一个新的文件,所以不可能出现文件不存的问题

翻了一下描述文档发现

 

复制粘贴之后,你会发现一个问题就是副本和原件的文件大小不一样

副本比原件的文件大

原因如下图

解决方案就是要用到FileInputStream方法中的read方法中的返回值

修改代码如下

 

缓冲流概述

缓冲流重点在缓冲这两个字,也就是说如果将缓冲流去掉是没有影响的

这里说的没有影响是对程序的逻辑上面没有影响,实际的速度可能会有影响

 

这里引入缓冲流是为了让文件不再从硬盘读取数据

而是从内存中读取数据,这样可以加快程序的运行效率

下面说一下缓冲流的工作过程吧!如下图

简单解释一下上图吧!

这里是以复制粘贴为例子,原件A中的数据通过FileInputStream将数据不直接写入到程序中

,而是将程序写入到缓冲输入流中,然后缓冲输入流再将数据写入到程序中

复制过程就完成了

下面是粘贴过程

粘贴过程其实就是将数据写入到文件中的过程

首先程序将数据写入到缓冲输出流中,再通过字节输出流将数据写入到文件中

 

关于缓冲输出流那一部分的执行过程开始有点疑惑,看了一下源码,好像不疑惑了

之前总感觉应该先是字节输出流将数据从程序中读出来,再翻放入到缓冲输出流

不过事实不是这样,只是写法是那样写,在程序中的顺序

源码如下

 

 

下面介绍一下两个类吧

 

BufferedInputStream

构造方法

 

从构造方法来看可以是任何InputStream的子类

第二个构造方法可以指定缓冲流的大小

这里还有一个数组,用于存放数据,如下

 

常用方法如下(和基本的输入输出流用法其实差不多)

 

BufferedOutputStream

构造方法

 

从构造方法来看,也可以将OutputStream的任何子类

第二个构造方法可以设置缓冲流的大小

常用方法

 

 

这里的flush方法表示清空缓冲区

这里解释一下,如下

缓冲区的工作原理

比如一个缓冲区的大小是20个字节(当然实际不可能这么小)

如果存入到缓冲区的数据大小不到20个字节

那么就不会触发write方法

那么数据就不会全部写入到文件中

所以在缓冲区不满的情况下,会调用flush进行缓冲区的清空

其实close也可以释放资源和清空缓冲区

 

使用和缓冲流和不使用缓冲流的对比试验

下面比较一下

复制粘贴文件

没有使用缓冲区和使用了缓冲区的总共耗费时间

 

首先没有使用缓冲区

代码如下

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
//没有使用缓冲区
public class FileTest {

	public static void main(String[] args) {
		try {
			FileInputStream fis=new FileInputStream("d://test1//womanOne.jpg");
			FileOutputStream fos=new FileOutputStream("d://test1//womanOnecopyth.jpg");
			
			int n=0;
			byte[] b=new byte[1024];
			//计时开始
			long start=System.currentTimeMillis();
			while((n=fis.read(b))!=-1) {
				fos.write(b,0,n);
			}
			
			fis.close();
			fos.close();
			//计时结束
			long end=System.currentTimeMillis();
			long time=end-start;
			System.out.println("总共耗时:" + time);
			
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}
}

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 Filetest2 {

	public static void main(String[] args) {
		try {
			FileInputStream fis = new FileInputStream("d://test1//womanOne.jpg");
			BufferedInputStream bis=new BufferedInputStream(fis);
			FileOutputStream fos = new FileOutputStream("d://test1//womanOnecopy2.jpg");
			BufferedOutputStream bos=new BufferedOutputStream(fos);
			
			int n = 0;
			byte[] b = new byte[1024];
			//计时开始
			long start = System.currentTimeMillis();
			while ((n = bis.read(b)) != -1) {
				bos.write(b, 0, n);
			}
			bos.flush();
			
			fis.close();
			fos.close();
			bis.close();
			bos.close();
			//计时结束
			long end = System.currentTimeMillis();
			long time = end - start;
			System.out.println("总共耗时:" + time);

		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

}

复制粘贴同一个文件,可以看出使用缓冲区和不使用缓冲区的区别是非常大的

不使用缓冲区的时间为22毫秒

使用缓冲区的时间为5毫秒

快了4.4倍,这就是使用缓冲区的好处

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值