JavaIO流与NIO

IO?NIO?

IO

按照流的流向分的话,可以分为输入流和输出流。

按照操作单元规划分的话,可以划分字节流和字符流。

按照流的角色划分的话,可以划分位字节流和处理流。

处理流的概念就是:增强基本流的功能(字节流和字符流)

Java IO 涉及的有40多个类,但是都是从4个抽象类基类中派生出来的。


扩展

AutoCloseable 接口

一个实现方法close();

一个对象在关闭之前可能会持有资源,如果close()方法处在try退出带有with-resource快时,将会在退出前,将调用AutoCloseable接口的close()方法。

幂等性 对于同一操作,无论一次还是多次,产生的效果和结果都是一样的,不会因为次数而变化。

image-20240820093124193


IO

1
2
3
4
5
graph LR
IO --> A(Reader-字符读取)
IO --> A2(Writer-字符写出)
IO --> A3(InputStream-字节读取)
IO --> A4(OutputStream-字节写出)

NIO

Java1.4引进

Buffer 是什么?

Buffer是一个容器,它包含数据的存储区(字节流和字符流),并提供操作这些数据的方法。

Buffer的几个核心概念

存储数据 是通道(Channel)的最大帮手。存储通道获取的数据,写入通道的数据。(**

位置(Position) Buffer中的数据当前位置,读和写都是相对于这个位置 进行,读数据位置会往前,写数据也会往前,读完数据不会删除,写数据会覆盖旧数据 比如我clear后,位置变为0。表示没有数据可以读,或者写入的意思。下次读取返回将会是-1.

读取数据 位置(Position)会往前走,走到缓冲区的limit。

进入缓冲区

1
2
3
4
5
6
7
8
9
10
11
        ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
//读取通道的文件
fileChannel.read(byteBuffer);
//进入缓存前 position为 9 limit为1024
byteBuffer.flip()//比如有9个数据进去
//进入缓存后 Postion为0 limit为9
while(byteBuffer.hasRemaining()){
//只要没走到 9 则一直走
System.out.print((char) byteBuffer.get());
}
byteBuffer.clear();//位置变为0,limit变为1024;虽然数据不会删除,但是已经读不到了,只能被写后覆盖数据。

写入“hello nio”文本

读取文本内容输出为

image-20240820105706238

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;

public class NIO {
public static void main(String[] args) {
String content = "hello nio";
Path path = Path.of("nio.txt");

//写入文件
try (FileChannel open = FileChannel.open(path, StandardOpenOption.CREATE,StandardOpenOption.WRITE))
{
ByteBuffer buffer = ByteBuffer.allocate(1024);
buffer.clear();
buffer.put(content.getBytes());
buffer.flip();
open.write(buffer);
}catch (Exception ex){
ex.printStackTrace();
}

//读入文件
try (FileChannel fileChannel = FileChannel.open(path,StandardOpenOption.READ)){
ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
int byteReader = fileChannel.read(byteBuffer);
while(byteReader != - 1){
byteBuffer.flip();
while (byteBuffer.hasRemaining()){
System.out.print((char) byteBuffer.get());
}
byteBuffer.clear();
byteReader = fileChannel.read(byteBuffer);
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}


总结

  • Java IO
    • 阻塞 I/O
    • 面向流
    • 使用简单,但在高并发场景下性能较差
  • Java NIO
    • 非阻塞 I/O
    • 使用缓冲区和通道
    • 支持选择器,适合高并发场景
    • 提供更高效的数据处理能力