【Java回顾】Day7 Java IO|分类(传输方式,数据操作)|零拷贝和NIO

# Java IO 知识体系

IO-分类(传输,操作)

传输方式

  • 字节流

  • 字符流

  • 字节流和字符流的区别

    • 字节流读取单个字节,字符流读取单个字符
    • 字节流来处理二进制文件(图片,MP3,视频文件),字符流(文本文件(特殊的二进制文件,使用某种编码,人可以阅读))
    • 字节流给计算机处理的,字符流给人看的。
  • 字节转字符Input/OutputStreamReader/Writer

    • 编码是将字节转字符,解码是将字符转字节

数据操作

  • 文件(file)
  • 数组([])
  • 管道操作
  • 基本数据类型
  • 缓冲操作
  • 打印
  • 对象序列化反序列化
  • 转换

零拷贝和NIO概述

NIO

  • 参考:https://javaguide.cn/java/io/io-model.html#nio-non-blocking-new-i-o

  • NIO是IO多路复用模型

    • 线程首先发起调用,询问内核数据是否准备就绪。等准备就绪后,用户线程再发起read调用(数据从内核空间->用户空间)是阻塞的。

      • select调用,支持一次查询多个系统调用的可用状态,几乎所有的操作系统都支持。
      • epoll调用,linux 2.6内核,select调用的增强版本,优化IO执行效率
  • NIO中的多路复用器selector

    *

  • 在高并发和高延迟的环境,适合用NIO提交效率。

  • 组成部分(3个)

    • Buffer缓冲区:读写。读:从Channel到buffer;写:从buffer到Channel。

    • Channel通道:双向可读可写的数据传输通道,实现数据的输入和输出。

    • Selector选择器:一个线程处理多个Channel,基于事件驱动的I/O多路复用模型。多个channel由selector来分配线程处理事件

  • 详解

    • Buffer,BIO是缓冲流,NIO是缓冲区

      • 默认是写模式,flip()切换到读模式;clear()或compact()切换到写模式

      • 核心代码

        • 用静态方法创建,CharBuffer buffer = CharBuffer.allocate(8);
        • put写数据,buffer.put('a').put('b').put('c');
        • get读数据,while (buffer.hasRemaining()) {
          System.out.print(buffer.get());
          }
        • 写→读,buffer.flip();
        • 读→写,buffer.clear();
      复制代码
        import java.nio.*;
      
        public class CharBufferDemo {
            public static void main(String[] args) {
                // 分配一个容量为8的CharBuffer
                CharBuffer buffer = CharBuffer.allocate(8);
                System.out.println("初始状态:");
                printState(buffer);
      
                // 向buffer写入3个字符
                buffer.put('a').put('b').put('c');
                System.out.println("写入3个字符后的状态:");
                printState(buffer);
      
                // 调用flip()方法,准备读取buffer中的数据,将 position 置 0,limit 的置 3
                buffer.flip();
                System.out.println("调用flip()方法后的状态:");
                printState(buffer);
      
                // 读取字符
                while (buffer.hasRemaining()) {
                    System.out.print(buffer.get());
                }
      
                // 调用clear()方法,清空缓冲区,将 position 的值置为 0,将 limit 的值置为 capacity 的值
                buffer.clear();
                System.out.println("调用clear()方法后的状态:");
                printState(buffer);
      
            }
      
            // 打印buffer的capacity、limit、position、mark的位置
            private static void printState(CharBuffer buffer) {
                System.out.print("capacity: " + buffer.capacity());
                System.out.print(", limit: " + buffer.limit());
                System.out.print(", position: " + buffer.position());
                System.out.print(", mark 开始读取的字符: " + buffer.mark());
                System.out.println("\n");
            }
        }
    • Channel 全双工

      • 常用通道

        • FileChannel 文件访问通道
        • SocketChannel,ServerSocketChannel TCP通信通道
        • DatagramChannl UDP通信通道
      • 核心方法

        • 读,读并写入到Buffer中
        • 写,将buffer数据写入channel中
      复制代码
        RandomAccessFile reader = new RandomAccessFile("/Users/guide/Documents/test_read.in", "r"))
        FileChannel channel = reader.getChannel();//得到一个channel
        ByteBuffer buffer = ByteBuffer.allocate(1024);//字节缓冲区buffer
        channel.read(buffer);//读
    • Selector

      • **epoll()**一个多路复用器Selector可以同时轮询多个Channel,由于JDK使用了epoll()代替select实现,因此没有最大连接句柄1024/2048的限制。可以连接成千上万的客户端

      • 监听事件类型

        • SelectionKey.OP_ACCPET 通道接受连接的事件,用于ServerSocketChannel
        • SelectionKey.OP_CONNECT 完成连接的事件,SocketChannel
        • SelectionKey.OP_READ 通道准备好进行读取的事件,有数据可读
        • SelectionKey.OP_WRITE,通道准备好写入的事件,写入数据

NIO零拷贝

  • 解决操作系统在处理I/O操作时频繁复制数据的问题

  • 零拷贝:执行IO操作时,CPU不需要将数据从一个存储区域复制到另一个存储区域,从而可以减少上下文切换以及CPU的拷贝时间

  • 必备2次DMA(Direct memory access),依赖硬件完成,零拷贝是减少了CPU拷贝及上下文切换

  • Java对零拷贝的支持

    • MappedByteBuffer
    • FileChannel
    • S

IO-分类(传输,操作)

传输方式

  • 字节流

  • 字符流

  • 字节流和字符流的区别

    • 字节流读取单个字节,字符流读取单个字符
    • 字节流来处理二进制文件(图片,MP3,视频文件),字符流(文本文件(特殊的二进制文件,使用某种编码,人可以阅读))
    • 字节流给计算机处理的,字符流给人看的。
  • 字节转字符Input/OutputStreamReader/Writer

    • 编码是将字节转字符,解码是将字符转字节

数据操作

  • 文件(file)
  • 数组([])
  • 管道操作
  • 基本数据类型
  • 缓冲操作
  • 打印
  • 对象序列化反序列化
  • 转换

零拷贝和NIO概述

NIO

  • 参考:https://javaguide.cn/java/io/io-model.html#nio-non-blocking-new-i-o

  • NIO是IO多路复用模型

    *

    • 线程首先发起调用,询问内核数据是否准备就绪。等准备就绪后,用户线程再发起read调用(数据从内核空间->用户空间)是阻塞的。

      • select调用,支持一次查询多个系统调用的可用状态,几乎所有的操作系统都支持。
      • epoll调用,linux 2.6内核,select调用的增强版本,优化IO执行效率
  • NIO中的多路复用器selector

    *

  • 在高并发和高延迟的环境,适合用NIO提交效率。

  • 组成部分(3个)

    • Buffer缓冲区:读写。读:从Channel到buffer;写:从buffer到Channel。
    • Channel通道:双向可读可写的数据传输通道,实现数据的输入和输出。
    • Selector选择器:一个线程处理多个Channel,基于事件驱动的I/O多路复用模型。多个channel由selector来分配线程处理事件
  • 详解

    • Buffer,BIO是缓冲流,NIO是缓冲区

      • 默认是写模式,flip()切换到读模式;clear()或compact()切换到写模式

      • 核心代码

        • 用静态方法创建,CharBuffer buffer = CharBuffer.allocate(8);
        • put写数据,buffer.put('a').put('b').put('c');
        • get读数据,while (buffer.hasRemaining()) {
          System.out.print(buffer.get());
          }
        • 写→读,buffer.flip();
        • 读→写,buffer.clear();
      复制代码
        import java.nio.*;
      
        public class CharBufferDemo {
            public static void main(String[] args) {
                // 分配一个容量为8的CharBuffer
                CharBuffer buffer = CharBuffer.allocate(8);
                System.out.println("初始状态:");
                printState(buffer);
      
                // 向buffer写入3个字符
                buffer.put('a').put('b').put('c');
                System.out.println("写入3个字符后的状态:");
                printState(buffer);
      
                // 调用flip()方法,准备读取buffer中的数据,将 position 置 0,limit 的置 3
                buffer.flip();
                System.out.println("调用flip()方法后的状态:");
                printState(buffer);
      
                // 读取字符
                while (buffer.hasRemaining()) {
                    System.out.print(buffer.get());
                }
      
                // 调用clear()方法,清空缓冲区,将 position 的值置为 0,将 limit 的值置为 capacity 的值
                buffer.clear();
                System.out.println("调用clear()方法后的状态:");
                printState(buffer);
      
            }
      
            // 打印buffer的capacity、limit、position、mark的位置
            private static void printState(CharBuffer buffer) {
                System.out.print("capacity: " + buffer.capacity());
                System.out.print(", limit: " + buffer.limit());
                System.out.print(", position: " + buffer.position());
                System.out.print(", mark 开始读取的字符: " + buffer.mark());
                System.out.println("\n");
            }
        }
    • Channel 全双工

      • 常用通道

        • FileChannel 文件访问通道
        • SocketChannel,ServerSocketChannel TCP通信通道
        • DatagramChannl UDP通信通道
      • 核心方法

        • 读,读并写入到Buffer中
        • 写,将buffer数据写入channel中
      复制代码
        RandomAccessFile reader = new RandomAccessFile("/Users/guide/Documents/test_read.in", "r"))
        FileChannel channel = reader.getChannel();//得到一个channel
        ByteBuffer buffer = ByteBuffer.allocate(1024);//字节缓冲区buffer
        channel.read(buffer);//读
    • Selector

      • **epoll()**一个多路复用器Selector可以同时轮询多个Channel,由于JDK使用了epoll()代替select实现,因此没有最大连接句柄1024/2048的限制。可以连接成千上万的客户端
      • 监听事件类型
        • SelectionKey.OP_ACCPET 通道接受连接的事件,用于ServerSocketChannel
        • SelectionKey.OP_CONNECT 完成连接的事件,SocketChannel
        • SelectionKey.OP_READ 通道准备好进行读取的事件,有数据可读
        • SelectionKey.OP_WRITE,通道准备好写入的事件,写入数据

NIO零拷贝

  • 解决操作系统在处理I/O操作时频繁复制数据的问题

  • 零拷贝:执行IO操作时,CPU不需要将数据从一个存储区域复制到另一个存储区域,从而可以减少上下文切换以及CPU的拷贝时间

  • 必备2次DMA(Direct memory access),依赖硬件完成,零拷贝是减少了CPU拷贝及上下文切换

  • Java对零拷贝的支持

    • MappedByteBuffer

    • FileChannel

相关推荐
百***92021 分钟前
java进阶1——JVM
java·开发语言·jvm
蓝桉~MLGT8 分钟前
Python学习历程——Python面向对象编程详解
开发语言·python·学习
Evand J9 分钟前
【MATLAB例程】2雷达二维目标跟踪滤波系统-UKF(无迹卡尔曼滤波)实现,目标匀速运动模型(带扰动)。附代码下载链接
开发语言·matlab·目标跟踪·滤波·卡尔曼滤波
larance12 分钟前
Python 中的 *args 和 **kwargs
开发语言·python
Easonmax15 分钟前
用 Rust 打造可复现的 ASCII 艺术渲染器:从像素到字符的完整工程实践
开发语言·后端·rust
迦蓝叶19 分钟前
RDF 与 RDFS:知识图谱推理的基石
java·人工智能·数据挖掘·知识图谱·语义网·rdf·rdfs
lsx20240620 分钟前
Rust 宏:深入理解与高效使用
开发语言
百锦再20 分钟前
选择Rust的理由:从内存管理到抛弃抽象
android·java·开发语言·后端·python·rust·go
yaoxin52112321 分钟前
238. Java 集合 - 使用 ListIterator 遍历 List 元素
java·python·list
小羊失眠啦.23 分钟前
深入解析Rust的所有权系统:告别空指针和数据竞争
开发语言·后端·rust