2021.01.31 第一阶段 17

*1、递归和File的练习
2、IO概述
3、字节流
4、字符流
*

一、递归和File的练习

(一)练习
键盘录入一个文件夹路径,使用递归打印这个文件夹下的所有文件的绝对路径
分析:
一个方法:使用递归必须要有方法自己调用自己
两个分支:
需要递归:遇到文件夹,就重复上一次打开文件夹的动作,获取里面的内容
不用递归:遇到文件,就不需要递归,而是直接获取打印文件的绝对路径即可

import java.io.File;
import com.offcn.homework.Homework04;
/**
* 键盘录入一个文件夹路径,使用递归打印这个文件夹下的所有文件的绝对路径
*
*/
public class Demo01_Exercise {
	public static void main(String[] args) {
		File dir = Homework04.getDir();
		printFilePath(dir);
	}
	public static void printFilePath(File dir) {
		//1.打开文件夹,将文件夹下所有的内容,全都转为File对象,便于操作
		File[] files = dir.listFiles();
		//2.遍历获取每一个File对象,进行具体操作
			for (File file : files) {
				//3.如果是文件,就打印绝对路径,如果是文件夹,就进入到文件夹中,操作内容
				if(file.isFile()) {
					System.out.println(file.getAbsolutePath());
				} else {
					printFilePath(file);
			}
		}
	}
}

(二)总结
1、所有能够使用递归完成的操作都有其他的解法,但是其他的解法相较于递归而言,比较难并且不方便操作
2、递归的优点:代码比较简单,按照递归的方式思考,比较容易
3、递归的缺点:递归是将所有的方法一口气全部加载进栈,之后再一个个执行弹栈,如果内存较小,或
者数据量巨大的时候,容易造成:StackOverFlowError
4、StackOverflow是一个国外网站的名称,类似于是一个专业版的知乎

二、IO概述

(一)基本概念
1、IO:是input和output的缩写,input输入,output输出
2、【Java中,所有的IO都是站在内存的角度说明】,一切其它设备进内存的操作,都是输入;一切内存到其他设备的操作,都是输出。
3、基本概念:
(1)硬盘:用于存储数据
(2)内存:用于数据指令执行
(二)IO分类
1、分类的方式有两种:按照流向分,按照功能分
2、按照流向分:
(1)输入流:从其它设备到内存
(2)输出流:从内存到其它设备
3、按照功能分:
(1)字节流:可以直接操作文件的字节信息
(2)字符流:一般用于操作文本文档的字符内容
4、体系结构:
在这里插入图片描述
(三)IO程序书写的注意事项
1、【所有IO流对象,在使用完毕之后,都要记得关闭资源】
2、Java所有IO相关的内容,都在IO包下,记得导包,并且不要导错
3、大部分IO流存在一些编译时异常,我们需要合理处理异常

三、字节流

(一)概述
1、可以直接操作字节信息的流对象,计算机中所有内容都用字节信息进行存储,所以这种流可以操作所有内容
2、根据流向,可以分为字节输入流,字节输出流
3、顶层抽象父类是:InputStream和OutputSream
4、根据交互设备的不同,有不同的实现子类,例如和磁盘交互,用于操作磁盘文件的实现类:
FileInputStream、FileOutputStream
(二)InputStream
1、字节输入流的顶层抽象父类
2、常用方法:
(1)read() 从输入流中读取数据的下一个字节
(2)read(byte[] b) 从输入流中读取一定数量的字节,并将其存储在缓冲区数组 b 中
(3)available() 返回要读取的文件中总的字节个数
(4)close() 关闭资源
3、因为InputStream是一个抽象类,所以无法实例化,如果要使用,需要根据具体的交互设备,创建实现子类的对象
(三)FileInputStream
1、是InputStream的一个具体的实现子类,用于和磁盘上的文件进行交互
2、构造方法:
(1)FileInputStream(String name) 使用字符串表示一个文件的路径,创建一个字节流对象,将
来用于读取文件字节信息(将文件的字节信息输入到内存)
(2)FileInputStream(File file) 使用File对象表示一个文件的路径,创建一个字节流对象,将来用
于读取文件字节信息(将文件的字节信息输入到内存)
3、常用方法:
(1)read() 从输入流中读取数据的下一个字节信息,返回它的int表示形式,当我们已经读取到了文
件末尾,则会返回-1。在实际操作中,即便文件中的内容有负数存在,读取到以后,也会是一个整数,
不可能在内存中出现负数,如果这的返回了负数,那一定是流到达末尾,自动返回的
(2)read(byte[] b) 从输入流中读取一定数量的字节,并将其存储在缓冲区数组 b 中
(四)OutputStream
1、字节输出流的顶层抽象父类
2、常用方法:
(1)write(int b) 向输出流对象所关联的位置输出一个字节信息
(2)write(byte[] b) 向输出流对象所关联的位置输出一个字节信息的数组
(3)write(byte[] b, int off, int len) 向输出流对象所关联的位置输出一个字节信息数组的一部分
(4)flush() 刷新缓冲区
3、这个类型是抽象的,根据交互设备的不同,由不同的实现子类来创建对象
(五)FileOutputStream
1、可以将内存中的字节信息,输出到指定的文件中
2、构造方法:
(1)FileOutputStream(String name) 创建输出流对象,可以将字节信息输出到String字符串表示的具体文件中
(2)FileOutputStream(File file) 创建输出流对象,可以将字节信息输出到File对象表示的具体文件中
3、注意事项:
(1)使用字节输出流,将内存中Java代码提供的字节信息输出到磁盘上的文件里,不存在编码操作,也不存在解码操作,仅仅是将字节信息,从内存中输出到了磁盘中
(2)但是当我们使用某些格式打开文件的时候,例如txt,就会按照txt的规则,将文件中的字节信息解码成人类语言
(六)文件拷贝
1、含义:将一个文件中的字节信息,拷贝到另一个文件中
2、本质:从一个文件中,使用输入流读取一个字节信息,将这个字节信息,通过输出流,输出到另外一
个文件中
3、图示:
在这里插入图片描述
(七)文件拷贝效率提升
1、使用逐个字节拷贝的方式,效率非常低:
(1)磁盘运行速度慢,频繁访问磁盘效率会变低
(2)每次拷贝一个字节信息,就要访问2次磁盘,次数过多本身就会降低效率
2、提升思路:一次多读取一些字节信息,一次多输出一些字节信息,减少访问磁盘次数,来提高效率
3、方式一:使用read(byte[] arr)方法,一次读取一个数组长度的字节信息,结合write(byte[] arr)方
法,将一整个数组直接写出,数组的大小就是文件中字节个数
4、方拾二:由于方式一,数组等于文件字节数,当文件过大,比计算机内存还要大,就无法实现用大数
组拷贝,可以将数组设置小一点,也可以提升效率。例如:数组长度设置为2
5、方式三:由于方拾二中,数组的长度问题,当文件字节个数为奇数的时候,而数组如果定义为偶数,
最后一次的拷贝,很有可能数组装不满,会带有最后一次和倒数第二次的拷贝结果,输出的时候,又是
整个数组进行输出的,所以结果会有问题。输出是产生问题的关键!输出的时候,本次读取到了多少内
容,就输出多少内容,没有读取到的就不输出,要使用write(byte[] , int index, int len)进行输出,可以
解决问题
6、注意事项:我们以后拷贝,都采用小数组的方案
(1)数组的大小可以自己设置,数组越大,效率越高,因为访问磁盘的次数越少
(2)一般情况下,数组的容积都采用1024的整数倍,官方经常使用1024*8作为缓冲区的大小
(八)read()方法和read(byte[] arr)方法的总结
1、int read() 一次读取一个字节信息,返回的是读取到的具体字节信息的int表示形式,当到达文件末尾,返回-1
2、int read(byte[] arr) 一次读取一个数组长度的字节信息,返回的是当前一次读取到的字节个数,当到达文件末尾,返回-1

三、高效缓冲字节流

1、高效缓冲字节输入流:BufferedInputStream,高效缓冲字节输出流:BufferedOutputStream
2、高效缓冲流都是包装类:本身不具有读写功能,只是在其他具有读写功能的流上进行功能的加强,例
如:FileInputStream和FileOutputStream本身效率不高,但是通过高效流加强,效率就会得到提升
3、构造方法:
(1)高效缓冲字节输入流:BufferedInputStream(InputStream in) 将参数指定的、具有读写功能
的流传入,形成一个具有高效读写功能的流对象
(2)高效缓冲字节输出流:BufferedOutputStream(OutputStream out) 将参数指定的、具有读
写功能的流传入,形成一个具有高效读写功能的流对象
4、使用:还是和加强之前的使用没有差别
5、高效的原因:
(1)BufferedInputStream高效原因:这个类型中封装了一个长度为8192的byte[],用于存储字节信
息,当调用read()方法的时,该对象一次性从磁盘获取8192个字节信息到数组中,只将第一个字节信息
返回给调用者,后来每一次调用read()方法的时候,都不会再去访问磁盘,而是从内存里的数组中拿取
一个字节信息返回给调用者,由于读取的是内存中的数组,而不是磁盘上的文件,减少了磁盘的访问次
数,所以效率提升明显。当8192个字节信息都读取完毕了,下一次,才会再去访问一次磁盘,再获取
8192个字节信息
(2)BufferedOutputStream高效原因:这个类型中封装了一个长度为8192的byte[],用于存储字节
信息,当调用write(int b)一次写出一个字节信息,并不会将字节信息直接输出到磁盘上,而是将自己信
息存储到数组中,当数组完全装满,才会向磁盘输出一次,一次输出8192个字节信息。这种方式也是减
少了访问磁盘的次数,来提高效率。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值