4_IO流

目录

IO流

输入输出(IO)是指计算机同任何外部设备之间的数据传递。

在这里插入图片描述

  1. 主要是把程序中的数据和磁盘里的数据进行交互。
  2. in:从磁盘里读取数据到程序里。
  3. out:从程序中写书数据到磁盘里。
  4. 分为字符流和字节流
    • 字符流:只能操作字符文件**.txt**。
    • 字节流:可以操作任何数据。

流的概念

数据的读写抽象成数据,在管道中流动。

  1. 流只能单方向流动。
  2. 输入流用来读取in
  3. 输出流用来写出out
  4. 数据只能从头到尾顺序的读写一次。

同步和异步

  • 同步就是一个任务的完成需要依赖另外一个任务时,只有等待被依赖的任务完成后,依赖的任务才能算完成,这是一种可靠的任务序列。要么成功都成功,失败都失败,两个任务的状态可以保持一致。
  • 异步是不需要等待被依赖的任务完成,只是通知被依赖的任务要完成什么工作,依赖的任务也立即执行,只要自己完成了整个任务就算完成了。至于被依赖的任务最终是否真正完成,依赖它的任务无法确定,所以它是不可靠的任务序列。我们可以用打电话和发短信来很好的比喻同步与异步操作。

阻塞和非阻塞

阻塞与非阻塞主要是从 CPU 的使用上来说的

当IO阻塞发生时,被阻塞的是发起IO操作的用户线程。

用户线程通过系统调用发起IO操作,由用户态进入内核态,把CPU的使用权还给了操作系统内核。

  • 操作系统内核在IO阻塞发生时,会将CPU的使用权分配给其他线程,或者其他进程,不会让CPU一直等待,CPU没有阻塞,是发起IO操作的线程被阻塞了
  • 非阻塞就是在这个慢的操作在执行时 CPU 去干其它别的事,等这个慢的操作完成时,CPU 再接着完成后续的操作。虽然表面上看非阻塞的方式可以明显的提高 CPU 的利用率,但是也带了另外一种后果就是系统的线程切换增加。增加的 CPU 使用时间能不能补偿系统的切换成本需要好好评估。

1. 同步阻塞(JAVA BIO)

同步并阻塞 IO,服务器实现模式一个连接一个线程,即客户端有连接请求时服务端就需要启动一个线程进行处理,如果这个连接不做任何事情,就会造成不必要的线程开销,当然可以通过线迟(Thread-Pool)程机制改善。

2. 同步非阻塞(JAVA NIO)

同步非阻塞,服务器实现模式一个请求一个线程,即客户端发送的连接请求都会注册到多路复用器上,多路复用器轮询到连接有 I/O 请求时才启动一个线程处理。用户进程也需要时不时地询问IO操作是否就绪,这就要求用户进程不停的去询问。

3. 异步阻塞(Java NIO)

异步阻塞,应用发起一个 IO 操作以后,不需要等待内核 IO 操作完成,内核完成 IO 操作以后会通知应用程序,这其实就是异步和同步的关键区别,同步必须等待或者主动去询问 IO 操作是否完成。那为什么说阻塞呢?因为此时是通过 select 系统调用来完成的,而 select 函数本身的实现方式就是阻塞的,但采用 select 函数有个好处就是它可以同时监听多个文件句柄(如果从UNP的角度看,select 属于同步操作。因为 select 之后,进程还需要读写数据),从而提高系统的并发性。

4. 异步非阻塞(Java AIO)

异步非阻塞,此种方式下,用户进程只需要发起一个IO操作便立即返回,等 IO 操作真正完成以后,应用程序会得到IO操作完成的通知,此时用户进程只需要对数据处理就好了,不需要进行实际的 IO 读写操作,因为真正的 IO 操作已经由操作系统内核完成了。

BIO、NIO、AIO

  1. BIO
    • 就是传统的 java.io包,它是基于流模型实现的,交互的方式是同步阻塞方式.
    • 在读入输入流或者输出流时,在读写动作完成之前,线程会一直阻塞在那里,它们之间的调用时可靠的线性顺序。
    • 适用于连接数目比较小且固定的结构。它对服务器资源要求比较高,并发局限于应用中
  2. NIO
    • 是 Java 1.4 引入的 java.nio 包
    • 提供了 Channel、Selector、Buffer 等新的抽象,可以构建多路复用的、同步非阻塞 IO 程序.
    • 适用于连接数目多且连接比较短的架构,比如聊天服务器,并发局限于应用中.
  3. AIO
    • 是 Java 1.7 之后引入的包,是 NIO 的升级版本
    • 提供了异步非堵塞的 IO 操作方式,所以人们叫它 AIO(Asynchronous IO).
    • 异步 IO 是基于事件回调机制实现的,也就是应用操作之后会直接返回,不会堵塞在那里,当后台处理完成,操作系统会通知相应的线程进行后续的操作。
    • 适用于连接数目多且连接比较长(重操作)的架构,比如相册服务器,充分调用 OS 参与并发操作,编程比较复杂

使用场景

  1. 在大多数场景下,不建议直接使用 JDK 的 NIO 类库(门槛很高),除非精通 NIO 编程或者有特殊的需求。在绝大多数的业务场景中,可以使用 NIO 框架 Netty 来进行 NIO 编程,其既可以作为客户端也可以作为服务端,且支持 UDP 和异步文件传输,功能非常强大。
  2. NIO 比 BIO 把一些无效的连接挡在了启动线程之前,减少了这部分资源的浪费。因为我们都知道每创建一个线程,就要为这个线程分配一定的内存空间。
  3. AIO 比 NIO 进一步改善是,将一些暂时可能无效的请求挡在了启动线程之前,比如在 NIO 的处理方式中,当一个请求来的话,开启线程进行处理,但这个请求所需要的资源还没有就绪,此时必须等待后端的应用资源,这时线程就被阻塞了。`

File文件流

封装一个磁盘路径字符串,可以是文件路径、文件夹路径、不存在的路径。

创建对象

new File(String str)

常用方法

文件、文件夹属性

方法用处
length()文件的字节量
exists()是否存在
ifFile()是否为文件
isDirectory()是否为文件夹
getName()获取文件名、文件夹名
getParent()获取父文件夹的路径
getAbsolutePath()获取绝对路径

创建、删除

方法用处
createNewFile()新建文件,已经存在返回false
mkdirs()新建多层不存在的文件夹
mkdir()新建一个不存在的文件夹
delete()删除文件、文件夹

文件夹列表

方法用处
list()返回String[] ,包含文件名
listFiles()返回File[] ,包含文件对象

递归删除文件夹


	public static void main(String[] args) {
		File f = new File("D:\\TEDU\\Desktop\\Test");
		method1(f);
		System.out.println("success");	
	}

	private static void method1(File f) {
		File[] fs = f.listFiles();
		// 刪除文件
		for (int i = 0; i < fs.length; i++) {
			if (fs[i].isFile()) {
				fs[i].delete();
			} else if (fs[i].isDirectory()) {
				if (!fs[i].delete()) {
					method1(fs[i]);
				}
				fs[i].delete();
			}
		}
		
		f.delete();
	}

字节流

专门用来读写 数据的,而且是各种类型 的数据. 被底层的一些工具类大量的使用.

继承结构

  1. 读取

    • InputStream – 父类是一个抽象类,不能new,只学习共性方法
      • FileInputStream – 子类学习怎么new,方法都是继承来的
      • BufferedInputStream – 子类学习怎么new,方法都是继承来的
  2. 写出

    • OutputStream – 父类是一个抽象类,不能new,只学习共性方法
      • FileOutputStream – 子类学习怎么new,方法都是继承来的
      • BufferedOutputStream – 子类学习怎么new,方法都是继承来的

字节流读取

InputStream父抽象类

​ 是一个抽象类,不能new,只学习共性方法

常用方法
abstract int read() 
//从输入流中读取数据的下一个字节。 

int read(byte[] b) 
//从输入流中读取一定数量的字节,并将其存储在缓冲区数组 b 中。 

int read(byte[] b, int off, int len) 
//将输入流中最多 len 个数据字节读入 byte 数组从off开始。 

void close() 
//关闭此输入流并释放与该流关联的所有系统资源。 
FileInputStream子类
new FileInputStream(File f);
new FileInputStream(String path);
BufferedInputStream子类
  1. 缓冲流、处理流,目的是提高程序读取和写出的性能。
  2. 先将数据缓存到char[],然后一起读取出来(默认8192个字符写入一次)
new BufferedInputStream(InputStream in)//用普通输入流创建对象

字节流写出

OutputStream父抽象类

​ 是一个抽象类,不能new,只学习共性方法

常用方法
void close()
//刷出去+关闭此输出流并释放与此流有关的所有系统资源。

void flush()
//刷新此输出流并强制写出所有缓冲的输出字节。一般写在关闭前

void write(byte[] b)
//将 b.length 个字节从指定的 byte 数组写入此输出流。

void write(byte[] b, int off, int len)
//将指定 byte 数组中从 off 开始的 len 个字节写入此输出流。

abstract  void write(int b)
//将指定的字节写入此输出流。
FileOutputStream子类
new FileOutputStream(String path);
new FileOutputStream(File f[,boolean append]);//true--追加;false--覆盖
BufferedOutputStream子类

该类实现缓冲的输出流。通过设置这种输出流,应用程序就可以将各个字节写入底层输出流中,而不必针对每次字节写入调用底层系统。

new BufferedOutputStream(OutputStream out);

字符流

字符流读取

常用于txt文件

Reader抽象类
int read()
//读取单个字符。

int read(char[] cbuf)
//将字符读入数组。

abstract  int read(char[] cbuf, int off, int len)
//将字符读入数组的某一部分。

int read(CharBuffer target)
//试图将字符读入指定的字符缓冲区。

abstract  void close()
//关闭该流并释放与之关联的所有资源。
FileReader子类

用来读取字符文件的便捷类

FileReader(String fileName)
//在给定从中读取数据的文件名的情况下创建一个新 FileReader。

FileReader(File file)
//在给定从中读取数据的 File 的情况下创建一个新 FileReader。
InputStreamReader子类
  1. InputStreamReader 是字节流通向字符流的桥梁:它使用指定的 charset 读取字节并将其解码为字符。
  2. 它使用的字符集可以由名称指定或显式给定,或者可以接受平台默认的字符集。
  3. 用来作为桥梁,把字节流转成字符流的桥梁。用来解决字符流读写乱码问题。
InputStreamReader(InputStream in ,String charsetName)
//String指定字符集

InputStreamReader(InputStream in)
//默认字符集
BufferedReader子类
  1. 从字符输入流中读取文本,缓冲各个字符,从而实现字符、数组和行的高效读取。
  2. 可以指定缓冲区的大小,或者可使用默认的大小。
BufferedReader(Reader in)

字符流写出

writer抽象类
void write(char[] cbuf)
//写入字符数组。

abstract  void write(char[] cbuf, int off, int len)
//写入字符数组的某一部分。

void write(int c)
//写入单个字符。

void write(String str)
//写入字符串。

void write(String str, int off, int len)
//写入字符串的某一部分。

abstract  void close()
//关闭此流,但要先刷新它。
FileWriter子类
FileWriter(String fileName)
//根据给定的文件名构造一个 FileWriter 对象。

FileWriter(String fileName, boolean append)
//根据给定的文件名以及指示是否附加写入数据的 boolean 值来构造 FileWriter 对象。
OutputStreamWriter子类
  1. OutputStreamWriter 是字符流通向字节流的桥梁:可使用指定的 charset 将要写入流中的字符编码成字节。
  2. 它使用的字符集可以由名称指定或显式给定,否则将接受平台默认的字符集。
  3. 用来作为桥梁,把字节流转成字符流的桥梁。用来解决字符流读写乱码问题。
OutputStreamWriter(OutputStream out, String charsetName)
//创建使用指定字符集的 OutputStreamWriter。

 OutputStreamWriter(OutputStream out)
//创建使用默认字符编码的 OutputStreamWriter。
BufferedWriter子类

将文本写入字符输出流,缓冲各个字符,从而提供单个字符、数组和字符串的高效写入。

BufferedWriter(Writer out)
//创建一个使用默认大小输出缓冲区的缓冲字符输出流。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值