IO

目录

一、IO流基本认识

1.1 字节流

1.2 字符流

1.3 高级流

二、IO流基本理解

2.1 IO流的分类

2.1.1 按照流的流向

2.1.2 按照处理数据单位

2.1.3 按照流的角色

2.2 IO流的选择

2.3 IO流的4个抽象基类

 2.4 字节流和字符流的区别

 2.4.1 使用场景

三、IO模型 

3.1 BIO(Blocking IO)

3.2 NIO(Non-blocking IO)

3.3 AIO(Asynchronous IO)

 3.4 IO多路复用

3.5 BIO/NIO/AIO区别

3.6 NIO的实现原理

四、序列化和反序列化


一、IO流基本认识

Java中的IO流是用于处理输入和输出的机制。分为输入流和输出流

Java的IO流主要分为两大类:字节流和字符流

1.1 字节流

  • InputStream和OutputStream:是所有字节输入流和输出流的抽象类,它们分别用于读取和写入字节
  • FileInputStream和FileOutputStream:用于从文件中读取字节和向文件中写入字节
  • ByteArrayInputStream和ByteArrayOutputStream:分别用于从字节数组中读取数据和将数据写入字节数组
InputStream in = new FileInputStream("input.txt");
OutputStream out = new FileOutputStream("output.txt");
FileInputStream fis = new FileInputStream("file.txt");
FileOutputStream fos = new FileOutputStream("output.txt");
ByteArrayInputStream bais = new ByteArrayInputStream(byteArray);
ByteArrayOutputStream baos = new ByteArrayOutputStream();

1.2 字符流

  • Reader和Writer:是所有字符输入流和输出流的抽象基类,它们分别用于读取和写入字符
  • FileReader和FileWriter:用于从文件中读取字符和向文件中写入字符
  • BufferedReader和BufferedWriter:用于提供缓冲区,提高读取和写入的效率
Reader reader = new FileReader("input.txt");
Writer writer = new FileWriter("output.txt");
FileReader fr = new FileReader("file.txt");
FileWriter fw = new FileWriter("output.txt");
BufferedReader br = new BufferedReader(new FileReader("file.txt"));
BufferedWriter bw = new BufferedWriter(new FileWriter("output.txt"));

1.3 高级流

  • ObjectInputStream和ObjectOutputStream:用于读取和写入对象。可以序列化和反序列化对象
  • DataInputStream和DataOutputStream:用于读取和写入基本数据类型
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("object.dat"));
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("object.dat"));

二、IO流基本理解

2.1 IO流的分类

2.1.1 按照流的流向

分为输入流和输出流,这里的输入输出是针对程序来说的

  • 输出:把程序(内存)中的内容输出到磁盘、光盘等存储设备中
  • 输入:读取外部数据(磁盘、光盘等存储设备的数据)到程序(内存)中

2.1.2 按照处理数据单位

分为字节流和字符流

  • 字节流:每次读取/写出一个字节,当传输的资料文件中有中文时,就会出现乱码
  • 字符流:每次读取/写出两个字节,有中文时,使用该流就可以正确传输显示中文。1字符=2字节

2.1.3 按照流的角色

分为节点流和处理流

  • 节点流:从或者向一个特定的地方(节点)读写数据。如FileInputSream
  • 处理流(包装流):是对一个已存在的流的连接和封装,通过所封装的流的功能调用实现数据读写。如BufferedReader

注意:一个IO流可以既是输入流又是字节流又或是以其他方式分类的流类型,是不冲突的

2.2 IO流的选择

根据三步选择适合自己的流:

1、选择输入流还是输出流:看是想向程序写数据,还是从程序取数据

2、考虑传输数据是每次传一个字节还是两个字节:是否存在中文

3、通过前两步可以选出一个合适的节点流了,如果想在此基础上增强功能,那么在处理流中选择一个合适的即可

2.3 IO流的4个抽象基类

  • 输入字节流:InputStream
  • 输出字节流:OutputStream
  • 输入字符流:Writer
  • 输出字符流:Reader

 2.4 字节流和字符流的区别

计算机中的一切最终都是二进制的字节形式存在,底层设备永远只接受字节数据。有时候要写字符串到底层设备,需要将字符串转成字节再进行写入。

字节流在操作时本身不会用到缓冲区(内存),是文件本身直接操作的;

字符流在操作时使用了缓冲区,通过缓冲区再操作文件

 2.4.1 使用场景

  • 字节流:一般用来处理图像、视频、PPT、Word类型的文件
  • 字符流:一般用于处理纯文本类型的文件,如TXT文件

字节流可以用来处理纯文本文件,但字符流不能用于处理图像视频等非文本类型的文件 

三、IO模型 

3.1 BIO(Blocking IO)

BIO属于同步阻塞IO模型,读取或写入数据的时候,线程将一直等待,知道数据准备就绪或写入操作完成。但在高并发环境下可能导致性能问题,因为线程在等待IO操作完成时被阻塞,无法执行其他任务。

3.2 NIO(Non-blocking IO)

NIO属于非阻塞IO模型,线程执行一个IO操作时不会等待,而是继续执行其他任务,这需要通过轮询或者使用回调函数等机制来检查IO操作是否完成。

3.3 AIO(Asynchronous IO)

 AIO属于异步IO模型,允许程序在执行IO操作时继续执行其他任务,而不需要等待

 3.4 IO多路复用

IO多路复用模型使用了操作系统提供的选择器(Selector)机制。通过选择器,一个线程可以监听多个通道上的IO事件,从而在单线程中处理多个连接。

3.5 BIO/NIO/AIO区别

 1、BIO

  • 工作原理:阻塞IO模型中,当一个线程执行IO操作时,它会被阻塞,知道IO操作完成,这会导致线程无法执行其他任务
  • 适用场景:适用于连接数较少、并发不高的场景

2、NIO

  • 工作原理:非阻塞IO模型中,一个线程可以处理多个连接,而不需要等待每个连接的IO操作完成。但线程需要通过轮询(polling)或者选择器(Selector)来检查哪些连接已经准备好进行IO操作
  • 适用场景:适用于高并发、连接数较多的场景。Java NIO提供了Selector、Channel等组件,可以更好地支持多连接的管理

3、AIO

  • 工作原理:异步IO模型中,程序发起IO操作后,可以继续执行其他任务。当IO操作完成时,系统会通知程序,并调用相应的回调函数
  • 适用场景:适用于需要处理大量并发连接的场景,并希望充分利用系统资源。Java NIO.2 提供了AIO支持,通过AsynchronousChannel和CompletionHandler实现异步IO操作

 总结:

BIO: 适用于连接数较少、并发不高的情况,简单易用。

NIO: 适用于高并发、连接数较多的网络应用,通过选择器实现非阻塞 I/O。

AIO: 适用于需要处理大量并发连接、希望充分利用系统资源的情况,通过异步操作实现。

3.6 NIO的实现原理

 Java NIO的实现原理主要涉及到一下几个核心概念和组件:

Channel(通道):抽象概念,类似于传统的流,但更加灵活。Channel可以是读、写或者读写的,并且可以异步地进行IO操作

Buffer(缓冲区):是NIO中用于存储数据的容器。Channel从Buffer中读取数据,将数据写入Buffer中

Selector(选择器):它允许一个线程同时监控多个Channel,当其中的某个Channel发生读或写事件时,可以通过Selector得到通知。这样一个线程可以有效地管理多个网络连接

 工作原理可以分为以下几个步骤:

1、打开Channel:通过FileChannel、SocketChannel、ServerSocketChannel等类的静态方法open()打开一个通道

2、创建Buffer:创建一个或多个Buffer,用于读取或写入数据

3、将数据写入Channel:将数据写入Buffer,然后将Buffer中的数据写入Channel

4、从Channel读取数据:将Channel中的数据读取到Buffer中

5、注册Channel到Selector:通过Selector监听一个或多个Channel,当Channel上发生感兴趣的事件时,Selector将通知程序

6、处理事件:在一个循环中调用Selector的select()方法,该方法会阻塞至少一个注册的Channel发生了感兴趣的事件。然后通过迭代selectedKeys()获取SelectionKey,从而得知哪个Channel上发生了事件

四、序列化和反序列化

序列化机制:将对象转换成字节序列

对象的序列化:将一个Java对象写入IO流中

对象的反序列化: 从IO流中恢复该Java对象

若对象要支持序列化机制,则它的类需要实现Serializable接口。该接口是一个标记接口,它没有提供任何方法,只是标明该类是可以序列化的。Java的很多类已经实现了Serializable接口,如包装类、String、Date等。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值