2021.1.31 第一阶段 18

1、高效缓冲流效率的进一步提升
2、close方法和flush方法的区别
3、字符流
4、转换流

一、高效缓冲流效率的进一步提升
高效缓冲流,还可以使用小数组进行进一步的效率提升

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 Demo01_BufferUp {
	public static void main(String[] args) throws IOException {
	}
	public static void test2() throws FileNotFoundException, IOException {
		BufferedInputStream bis = new BufferedInputStream(newFileInputStream("Demo01.txt"));
	BufferedOutputStream bos = new 
							BufferedOutputStream(newFileOutputStream("Demo01_copy1.txt"));
	int len;
	long start = System.currentTimeMillis();
	byte[] b = new byte[1024];
	while((len = bis.read(b)) != -1) {
	bos.write(b, 0, len);
	}
	long end = System.currentTimeMillis();
	bis.close();
	bos.close();
	System.out.println(end - start);
	
	}
	public static void test1() throws FileNotFoundException, IOException {
	BufferedInputStream bis = new BufferedInputStream(newFileInputStream("Demo01.txt"));
	BufferedOutputStream bos = new BufferedOutputStream(new
											FileOutputStream("Demo01_copy1.txt"));
	int i;
	long start = System.currentTimeMillis();
	while((i = bis.read()) != -1) {
	bos.write(i);
	}
	long end = System.currentTimeMillis();
	bis.close();
	bos.close();
	System.out.println(end - start);
	}
}

二、close方法和flush方法的区别
1、高效缓冲字节输出输出流中有一个8192的byte[]数组,它访问磁盘、向磁盘输出字节信息的条件是:
当数组完全装满,才去访问一次磁盘,向磁盘输出字节信息,如果没有装满,不会输出
2、flush() 刷新缓冲区,强制将缓冲区中的内容,向目标位置输出一次,并且清空缓冲区
3、close方法实际上在调用flush方法,当我们调用close方法释放系统资源的时候,会先调用flus法
进行缓冲区刷新,确保数据正确完整,再关闭其他资源
4、区别:
(1)flush仅仅用于刷新缓冲区并强制输出缓冲区内容,并不会关闭流对象,流对象可以继续使用
(2)close方法在关闭资源之前,会调用flush方法,之后关闭资源。当close方法关闭资源后,流对
象就无法继续使用了
5、注意事项:我们使用高效流高效的原因是:减少访问磁盘的次数来提高效率。但是flush方法会强制
访问磁盘,如果频繁调用flush方法,就会增多访问磁盘的次数,进而降低系统效率。

三、字符流

(一)常见字符集
1、GBK:国标码,支持中文且兼容ASCII,其中一个英文占1个字节,中文占2个字节
2、UTF-8:万国码,支持各国语言,其中一个英文占1个字节,中文占3个字节
3、ISO-8859-1:拉丁语系国家的字符集,不支持中文
(二)使用字节流处理字符的问题
1、使用字节流正常拷贝文件:没有任何问题,因为字节流拷贝,就是将源文件中的字节信息,原封不动的搬运到目标文件中,源文件中什么样,目标文件中就是什么样
2、使用字节流拷贝文件的过程中,加入任务阅读(预览),预览到的内容可能会出现乱码:例如:读取纯中文的文件,一个汉字如果占2个字节,我们只读取一个字节预览,就会因为字节信息不完整而无法显示正确内容。如果动态判断文字占几个字节,可以正常解析,但是又存在很多文字不认识,无法知道占几个字节的问题,所以动态判断成本高,难度大。
(三)字符流的使用
1、顶层抽象父类:Reader(字符输入流)、Writer(字符输出流)
2、常用方法:
(1)Reader:
read() 读取单个字符,当到大文件末尾时,返回-1
read(char[] cbuf) 读取一个char[]的字符,返回读取到的字符个数,到大文件末尾时,返回-1
(2)Writer:
write(int c) 写出一个字符
write(char[] cbuf, int off, int len) 写出一个字符数组的一部分
write(String str) 写出一个字符串
write(String str, int off, int len) 写出字符串的一部分
3、抽象类不能实例化,所以需要根据交互设备的不同,使用不同的实现子类来实例化
4、使用:FileReader和FileWriter来进行实例化
(四)字符流拷贝
1、使用字符输入流读取信息,底层实际上在使用字节流读取,之后再内存中进行了解码操作
2、使用字符输出流输出信息,首先进行了编码操作,在内存中将字符信息编码为字节信息,之后通过字
节流将字节信息输出
3、原理图示:
在这里插入图片描述
4、使用场景:
(1)纯拷贝:建议使用字节流,虽然字节流本身没有缓冲区,但是如果加上缓冲区,在相同的条件
下,效率要比字符流高。因为如果具有同等条件,字节流是纯粹的字节信息搬运,但是字符流还要在内
存中多一个编解码操作,所以相比而言效率低
(2)拷贝过程中掺杂人为阅读:建议使用字符流,因为字符流可以显示正确且完整的字符信息,使用
字节流还需要自己进行动态判断,比较麻烦
(五)拷贝非纯文本文件
1、字节流可以正常拷贝非纯文本文件
2、字符流不能拷贝非纯文本文件
3、原因:字符流使用字节流将源文件的字节信息读取进内存之后,会按照【字符集】去对字节信息做编
解码操作,如果是图片、视频等的非纯文本文件的字节信息,按照【字符集】编解码会被损坏,所以,
字符流不能拷贝非纯文本文件
(六)字符流的效率提升
1、在高效缓冲字节流中,使用小数组拷贝,效率会进一步提升
2、结合以上原理,我们使用小数组结合字符流拷贝,效率能够得到进一步的提升

四、高效缓冲字符流

1、高效缓冲字符输入流:BufferedReader
2、高效缓冲字符输出流:BufferedWriter
3、使用:是一个包装类,本身不具有读写功能,需要将具有读写功能的流对象传入,对其进行封装,提升具有读写功能流对象的效率
4、特有方法:
(1)BufferedReader:readLine() 读取一个文本行,到达文件末尾返回null
(2)BufferedWriter:newLine() 换行
5、高效的原因:
(1)BufferedReader:底层是一个容量为8192的char[],每次调用read方法,只有第一次从磁盘中读取8192个字符信息,将字符信息存储到缓冲区中,并且将第一个字符信息返回给调用者,之后每次调用read,都会直接从缓冲区中获取字符信息,不会再去访问磁盘,直到缓冲区中的信息获取完,才会再起访问磁盘,减少了和磁盘的交互次数,提升效率
(2)BufferedWriter:每次调用write方法,不会将字符信息直接写出到磁盘,而是存入了高效输出流底层8192容量的char[]中,直到数组装满,才会将数组内容向磁盘输出一次,减少访问磁盘的次数,提升效率

五、转换流

1、使用字节流和字符流跨字符集拷贝文件,均会有乱码产生
2、产生原因:
(1)字节流:源文件是GBK编码,每个汉字2个字节,目标文件是utf-8编码,每个汉字3个字节,将源文件的2个字节搬运到目标文件中,目标文件按照3个字节解析的时候,还缺少一个字节信息,所以会乱码

(2)字符流:字符流对象在拷贝中内存里会进行编解码操作,此时编解码操作会依赖某个字符集进
行。因为我们平台默认的字符集是GBK,所以将字节信息从源文件读取到内存的时候都是8个字节,之后
的解码操作,按照默认字符集(GBK)进行,在内存中解码之后是正常的汉字;当输出的时候,会先查
询默认字符集(GBK)将汉字编码为对应的字节信息(8个字节),之后输出到目标文件中,目标文件是
utf-8,所以不能正常解析,会产生乱码
3、使用转换流解决跨平台拷贝的问题:
(1)InputStreamReader 是字节流通向字符流的桥梁
构造方法:InputStreamReader(InputStream in, String charsetName) 将字节流对象转换成字
符流对象,并且这个字符流对象可以通过参数指定字符集
(2)OutputStreamWriter 是字符流通向字节流的桥梁
构造方法:OutputStreamWriter(OutputStream out, String charsetName) 将字节流对象转换
成字符流对象,并且这个字符流对象可以通过参数指定字符集
4、解决原理:
(1)读取的时候,源文件是什么字符集,在内存中就按照什么字符集去解码
(2)输出的时候,目标文件是什么字符集,就按照目标文件的字符集去编码

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值