IO流
IO 流
类型
为什么要区分字节流和字符流
- java虚拟机转换字符需要消化性能,视频和图片等不需要字符,直接传字节就行
1. 字节流
1. InputStream/OutputStream
2. dataInputStream /OutputStream
- 读各种类型
3. ObjectInputStream/OutputStream
- 序列化和反序列化
- 不想要序列化的属性加上 `trasient`
2. 字符流
1. Reader/Writer
3. 特殊的流
1. RandomAccessFile
- 随机访问流,可以随机访问文件,可以用于分片上传
2. PrintWriter
- 字节打印流,sout就是使用的他
NIO
Buffer
重要属性:
- capacity
- limit
- positoin
- mark
两种状态
- 写模式(默认)
- 读模式
- 当这两种模式切换的时候上面的参数也会跟着变化
- 注意有坑,当你写入数据完成的时候,你要切换成读模式,以便让底层可以读buffer
Channel
- 全双工
- FileChannel(文件)、
- SocketChannel、ServerSocketChannel(TCP链接)、
- DataGramChannel(UDP链接)
Selector
-
工作原理
- channel通过注册事件给
Selector然后给一个SelectionKey,当事件完成的时候,转换为就绪状态,然后selector轮询出来,然后将这个Channel的SelectionKey放到就绪集合中,线程通过这个key去找到对应的channel读取数据/写入数据
- channel通过注册事件给
-
Selector 可以监听以下四种事件类型:
SelectionKey.OP_ACCEPT:表示通道接受连接的事件,这通常用于 ServerSocketChannel。SelectionKey.OP_CONNECT:表示通道完成连接的事件,这通常用于 SocketChannel。SelectionKey.OP_READ:表示通道准备好进行读取的事件,即有数据可读。SelectionKey.OP_WRITE:表示通道准备好进行写入的事件,即可以写入数据。
-
SelectionKey集合
- 所有Key集合: keys()获得
- 被选择的key集合: .selected()获得
- 取消的key集合: 不能获得
NIO使用方法
RandomAccessFile reader = new RandomAccessFile("/Users/guide/Documents/test_read.in", "r");
FileChannel channel = reader.getChannel();
ByteBuffer buffer = ByteBuffer.allocate(1024);
channel.read(buffer);
把任意IO流变成NIO
// 将任意 InputStream 包装成 ReadableByteChannel
ReadableByteChannel myChannel = Channels.newChannel(System.in);
如何遍历SelectionKey集合进行处理
Set<SelectionKey> selectedKeys = selector.selectedKeys();
Iterator<SelectionKey> keyIterator = selectedKeys.iterator();
while (keyIterator.hasNext()) {
SelectionKey key = keyIterator.next();
if (key != null) {
if (key.isAcceptable()) {
// ServerSocketChannel 接收了一个新连接
} else if (key.isConnectable()) {
// 表示一个新连接建立
} else if (key.isReadable()) {
// Channel 有准备好的数据,可以读取
} else if (key.isWritable()) {
// Channel 有空闲的 Buffer,可以写入数据
}
}
keyIterator.remove();
}
问题
// 字节流转换为字符流的桥梁
public class InputStreamReader extends Reader {
}
// 用于读取字符文件
public class FileReader extends InputStreamReader {
}
为什么缓冲流会减少io消耗
- 减少用户态和内核态的切换和cpu的上下文切换,
- 上下文切换会先保存数据,然后再加载数据,浪费时间
- 减少磁盘写入
- 磁盘写入和读取一次会读取一页或者一个扇区
- 一个写入多个就写到一页里面,可以减少磁盘操作