Java基础22-【Buffered缓冲流&DataInputStream&DataOutputStream】

Java基础22-Buffered缓冲IO流

Buffered缓冲IO流

缓冲IO流:
是处理流,负责在其他IO流基础上增加缓冲功能。提高效率

BufferedReader —> Reader
BufferedWriter —> Writer
BufferedInputStream —> InputStream
BufferedOutputStream —> OutputStream

BufferedReader除了继承了Reader的那些读的方法,还增加了一个:`String readLine()`读取一行(读取一个文本行)

BufferedWriter除了继承了Writer的那些写的方法,还增加了一个:`void newLine()`写换行符
 默认的缓冲区的大小:8192字节/字符
	@Test
	public void test01() throws IOException{
		//用它来读取一个文件,因为控制台只能显示文本数据,所以我们这里用纯文本文件来演示
		FileReader fr = new FileReader("1.txt");
		BufferedReader br = new BufferedReader(fr);
		
		//数据:1.txt --> fr --> br
		String str ;
		while((str = br.readLine()) != null){
			System.out.println(str);
		}
		
		br.close();
		fr.close();
	}

在这里插入图片描述
用缓冲流和没用缓冲流的区别:

@Test
	public void test02()throws IOException{
		long start = System.currentTimeMillis();
		FileReader fr = new FileReader("1.txt");
		BufferedReader br = new BufferedReader(fr);
		
		FileWriter fw = new FileWriter("11.txt");
		BufferedWriter bw = new BufferedWriter(fw);
		
		String str ;
		数据:1.txt --> fr --> br --> str --> bw --> fw -- >11.txt
		while((str = br.readLine()) != null){
			bw.write(str);
			bw.newLine();//换行
		}
		
		bw.close();
		fw.close();
		br.close();
		fr.close();
		
		long end = System.currentTimeMillis();
		System.out.println("毫秒:" + (end-start));
	}

在这里插入图片描述
不带缓冲流的

public class TestTxtCopy {
	
	@Test
	public void test01() throws IOException{
		long start = System.currentTimeMillis();
		copy("1.txt", "12.txt");
		long end = System.currentTimeMillis();
		System.out.println("毫秒:" + (end-start));
	}
	
	/*
	 * 纯文本文件的复制
	 */
	public void copy(String srcFileName, String destFileName) throws IOException{
		//1、选择IO流,并创建IO流
		FileReader fr = new FileReader(srcFileName);
		FileWriter fw = new FileWriter(destFileName);
		
		//2、一边读一边写
		char[] arr = new char[10];
		int len;
		//数据从  srcFileName文件 --》 fr --> arr数组 --> fw --> destFileName
		while((len = fr.read(arr)) != -1){
			fw.write(arr, 0, len);
		}
		
		//3、关闭
		fw.close();
		fr.close();
		
	}
}

在这里插入图片描述
可以看出有缓冲流速度更快,原因:

在这里插入图片描述
有缓冲流,先将数据都暂存到缓冲流里。达到一定数量后再一次性写进或者读出,不用每读一次或者写一次就马上读写,更节约时间
在这里插入图片描述
在这里插入图片描述
默认字节流对应的缓冲流大小为8192字节,字符流对应的为8192字符,也可以自己设置大小

8192=1024*8=8K

复制任意类型文件示例:

	@Test
	public void test03() throws IOException{
		long start = System.currentTimeMillis();
		copy("D:/software/IDEA/ideaIU-Ultimate-2017.1.4.exe","d:/idea.exe");
		long end = System.currentTimeMillis();
		System.out.println("毫秒:" + (end-start));
	}
	
	//复制任意类型的文件的功能
	//任意类型的文件,只能选择字节流
	public void copy(String srcFilename , String destFilename) throws IOException{
		FileInputStream fis = new FileInputStream(srcFilename);
		BufferedInputStream bis = new BufferedInputStream(fis);//fis比喻成内衣,bis是外套
		
		FileOutputStream fos = new FileOutputStream(destFilename);
		BufferedOutputStream bos = new BufferedOutputStream(fos);
		
		byte[] arr = new byte[10];
		int len;
		//数据: srcFilename --> fis --> arr --> fos --> destFilename
		while((len = bis.read(arr)) !=-1){
			bos.write(arr, 0, len);
		}
		
		bis.close();//先脱外套
		fis.close();//再脱内衣
		
		bos.close();
		fos.close();
	}
	注意关闭流的顺序,当有多个流套起来时,比如以上例子,bos套的fos,bis套的fis,一种方法只关外层的,即只关bos和bis,它会自动将内层的fos和fis关闭,另一种都关,但要注意顺序,先关外层,再关内层,若是顺序错了运行会报错,数据可能会少,因为顺序错误输出流关闭异常,输出流缓冲区里还有数据没处理,当正常关闭时,会自动刷一遍缓冲区,因为既没正常关闭流,又没自己刷一遍缓冲区,所以有数据缺失

fos和fis、bos和bis之间没有先后关系,因为没有依赖关系

关于换行符的说明

@Test
	public void test02()throws IOException{
		long start = System.currentTimeMillis();
		FileReader fr = new FileReader("1.txt");
		BufferedReader br = new BufferedReader(fr);
		
		FileWriter fw = new FileWriter("11.txt");
		BufferedWriter bw = new BufferedWriter(fw);
		
		String str ;
		数据:1.txt --> fr --> br --> str --> bw --> fw -- >11.txt
		while((str = br.readLine()) != null){
			bw.write(str);
			//bw.newLine();//换行
		}
		
		bw.close();
		fw.close();
		br.close();
		fr.close();
		
		long end = System.currentTimeMillis();
		System.out.println("毫秒:" + (end-start));
	}

在这里插入图片描述
运行完数据都在一行,因为br.redLine()按行读的时候,bufferedReader读取数据时将换行符当作数据的分隔符了,没把它当作数据的一部分,所以读取的时候没有取换行符,因此写的时候str里是不包含换行符的,就没有换行,下次写就挨在一起
要换行有两种:
1:自己加\n
bw.write(str+"\n");
2:每写完一次加一个newLine()
bw.newLine();//换行, 如例子里的注释

换行符的问题

@Test
	public void test05()throws IOException{
		FileWriter fw = new FileWriter("22.txt");
		fw.write("hello");
     	fw.write("\n");
		fw.write("world");
		fw.close();
	}

在这里插入图片描述
直接项目里打开换行了
但是若是文件用记事本打开会发现没有换行
在这里插入图片描述
原因:记事本是c语言,window自带的,在c语言里是 \r\n 两个构成换行符,所以一般为了跨平台,一般用newLine()换行,因为直接用\n大部分软件可能支持换行,但c支持的软件不能换行,要么就fw.write("\r\n");//\r本行结束,\n把光标移动到下一行,是两个动作

@Test
	public void test05()throws IOException{
		FileWriter fw = new FileWriter("22.txt");
		fw.write("hello");
//		fw.write("\n");
		fw.write("\r\n");//\r本行结束,\n把光标移动到下一行
		fw.write("world");
		fw.close();
	}

转换流:InputStreamReader

解码: 字节输入流转字符输入流的转换流,同 时还能指定编码方式
InputStreamReader:

案例:
在这里插入图片描述
文件编码为ANSI,就是操作系统当前平台的编码
操作系统中文:默认GBK或者GB2312,而eclipse控制台(或者工作空间)的编码为utf-8
读取文件:

	@Test
	public void test01() throws IOException{
		//乱码:d:/io.txt的编码是GBK,平台是UTF-8
		FileReader fr = new FileReader("d:/io.txt");
		char[] arr = new char[1024];
		int len = fr.read(arr);
		System.out.println(new String(arr,0,len));
		fr.close();
	}

在这里插入图片描述
会发现乱码,原因:d:/io.txt的编码是GBK,平台是UTF-8
处理方法:对应的编码解码

@Test
	public void test02() throws IOException{
		//String:解码
		//解码:字节-->字符
		FileInputStream fis = new FileInputStream("d:/io.txt");
		byte[] arr = new byte[10];
		int len = fis.read(arr);
		//String(byte[] bytes, String charsetName)
		//String(byte[] bytes, int offset, int length, String charsetName)
		System.out.println(new String(arr,0,len,"GBK"));
		fis.close();
	}

1
没有乱码

对于GBK来说,一个汉字两个字节,若是将byte数组长度设置为9,则最后一个汉字乱码,因为缺少一个字节,当文件过大或者中英文结合时,不好确认素组长度

另一种解码方法,解码IO流:InputStreamReader
解码:  字节输入流转字符输入流的转换流,同时还能指定编码方式
	@Test
	public void test03()throws IOException{
		//解码:字节-->字符
		FileInputStream fis = new FileInputStream("d:/io.txt");
		InputStreamReader isr = new InputStreamReader(fis,"GBK");//将fis流中的字节流按照GBK进行解码为字符流
		//数据:d:/io.txt(GBK)-->fis(纯字节)-->isr(GBK)解成字符流-->按字符读取
		char[] arr = new char[3];//字符数组
		int len = isr.read(arr);
		System.out.println(new String(arr,0,len));
		
		isr.close();
		fis.close();/注意关闭顺序
	}

在这里插入图片描述

转换流: OutputStreamWriter

编码:字符–》字节
把字符流转为字节流的转换流
OutputStreamWriter:
把字符流转为字节流,并且可以指定编码

@Test
	public void test01()throws IOException{
		//当前平台是UTF-8,文件是GBK
		String str = "柴老师永远18岁!";
		
		FileWriter fw = new FileWriter("d:/io.txt");
		fw.write(str);
		fw.close();
	}

在这里插入图片描述
写入乱码

解决方法1:用String的编码

@Test
	public void test02()throws IOException{
		//当前平台是UTF-8,文件是GBK
		//String:编码的方法  getBytes()
		//编码:字符--》字节
		String str = "柴老师永远18岁!";
		FileOutputStream fos = new FileOutputStream("d:/io.txt");
		fos.write(str.getBytes("GBK"));//无参是平台默认的
		fos.close();
	}

在这里插入图片描述
用转换流

@Test
	public void test03()throws IOException{
		//当前平台是UTF-8,文件是GBK
		//String:编码的方法  getBytes()
		//编码:字符--》字节
		String str = "柴老师永远18岁!永远美丽";
		FileOutputStream fos = new FileOutputStream("d:/io.txt");
		OutputStreamWriter oos = new OutputStreamWriter(fos, "GBK");
		
		oos.write(str);//数据:  str(字符)-->oos(字符)按照GBK编码为字节流-->fos --> io.txt
		
		oos.close();
		fos.close();
	}
	

在这里插入图片描述
转换流: OutputStreamWriter和InputStreamReader只能用于处理纯文本数据的编码和解码

数据IO流:DataInputStream和DataOutputStream

DataOutputStream
程序中有这样一组数据:
int num = 10;
char c = ‘好’;
double d = 88.88;
String info = “尚硅谷真好!”;
boolean good = true;

程序运行过程中,想要临时退出,下次希望从这个状态继续恢复执行。

希望Java能够输出各种数据类型的数据,读取时,能还原各种数据类型的数据。
因为这些数据不是纯文本,那么只能选择字节流。

@Test
	public void test01()throws IOException{
		int num = 10;
		char c = '好';
		double d = 188.88;
		String info = "尚硅谷真好!";
		boolean good = true;
		 
		FileOutputStream fos = new FileOutputStream("data.dat");//字节流,按字节输出
		/*fos.write(num);//错误的
		fos.write(c);
		fos.write((byte)d);//转换为byte数据会丢失,不转换报错*/
		DataOutputStream dos = new DataOutputStream(fos);
		
		dos.writeInt(num);
		dos.writeChar(c);
		dos.writeDouble(d);
		dos.writeUTF(info);//写字符串,按utf-8的方式来写字符串
		dos.writeBoolean(good);
		
		dos.close();
		fos.close();
	}

在这里插入图片描述
因为字符串是按utf-8得格式写得,所以能正常识别、看懂,其他的writeInt等按指定的编码方式写进去,utf-8解不了,这些数据只能java程序能解,外面得程序打开是乱码的,除非用另一个java程序去读取,所以java程序里的文件一般不取名.txt,一般这种文件取名.dat,然后用它对应的软件打开(这里即java程序),解决方法就是用DataInputStream读

DataInputStream:用.bat文件存进去,DataInputStream去读取

	@Test
	public void test02()throws IOException{
		FileInputStream fis = new FileInputStream("data.dat");
		DataInputStream dis = new DataInputStream(fis);
		
		int num = dis.readInt();
		char c = dis.readChar();
		double d = dis.readDouble();
		String s = dis.readUTF();
		boolean b = dis.readBoolean();
		
		System.out.println(num);
		System.out.println(c);
		System.out.println(d);
		System.out.println(s);
		System.out.println(b);
		
		dis.close();
		fis.close();
	}

在这里插入图片描述

数据类型不同,字节不同,只用FileOutputStream不知道按几个字节去解析,用DataInputStream,读的时候文件不存在运行会报错,写的时候文件不存在会创建一个文件

Java中IO流的类的体系设计,隐含了一个设计模式:装饰者设计模式

DataOutputStream在OutputStream的基础上,增加了很多方法:
writeXxx(…)

DataInputStream在InputStream的基础尚自,增加了很多方法:
Xxx readXxx()

要求:
用DataOutputStream写的文件或数据,得用DataInputStream来读取。
并且要求读的顺序与写的顺序要一致。比如写的时候先写得int在char,读的时候顺序也得一样,不然读出来数据不对

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值