Java
Python前端运维数据库
Java
Java
  • 新特性
    • Record
    • Optional
  • 面向对象
    • 面向对象基础
    • 构造方法
    • 继承与多态
    • 接口
    • 修饰符
    • 代码块
    • 接口(Interface)
    • 枚举类
  • IO流
    • IO
      • 字节流
      • 字符流
      • 缓冲流
      • 转换流
      • 操作ZIP
      • File 对象
    • NIO
      • Channel和Buffer
      • 异步文件通道AsynchronousFileChannel
      • Selector
      • Path/Files/Pipe
  • 反射
  • 内存分配
  • 集合
    • 简介
    • List
    • Set
    • Map
    • EnumMap
  • 日期与时间
    • Date和Calendar
    • Java8 新时间 ✨
      • LocalDateTime
      • ZonedDateTime
      • Duration
    • 时间格式化
      • SimpleDateFromat
      • DateTimeFormatter ✨
    • Instant
    • 实践
  • 网络编程
    • IP 地址
    • 网络模型
    • TCP 编程
    • UDP 编程
    • HTTP 编程
  • 加密和安全
  • 并发编程
    • 多线程
    • 线程与进程的区别
    • 线程组和线程优先级
    • 线程池
    • 线程锁
  • 异步任务
    • Future
    • CompletableFuture
      • 开启异步任务
      • 串行任务方法
      • 并行任务方法
      • 任务结束方法
      • 异常处理方法
      • 查看状态方法
      • 设置任务结果方法
  • 执行系统命令
  • Stream 流
    • Stream 流的创建
    • Stream 流串行与并行
    • Stream 流中间操作
    • Stream 流终端操作
  • Lambda 表达式
    • Lambda 表达式简介
    • Lambda 表达式语法
    • 方法引用
  • String
  • StringBuffer
由 GitBook 提供支持
在本页
  • Channel(通道)
  • Buffer(缓冲区)
  • FileChannel

这有帮助吗?

  1. IO流
  2. NIO

Channel和Buffer

通常,NIO中的所有IO都以Channel开头,数据可以从Channel读入Buffer,也可以从Buffer写入Channel。

以下是NIO中Channel实现类的列表,这些通道包括UDP+TCP网络IO和文件IO:

  • FileChannel :文件通道

  • DatagramChannel :数据报通道

  • SocketChannel :套接字通道

  • ServerSocketChannel :服务器套接字通道

以下是 NIO 中的核心 Buffer 实现,其实就是 7 种基本类型:

  • ByteBuffer

  • CharBuffer

  • ShortBuffer

  • IntBuffer

  • LongBuffer

  • FloatBuffer

  • DoubleBuffer

Channel(通道)

NIO 中的通道类似于流,单丝两者之间存在一些区别:

  • 通道可以读取和写入。流通常是单向的(读或写)

  • 通道可以异步读取和写入。

  • 通道始终读取或写入缓冲区,它只面向缓冲区。

// 文件内容 123456789
RandomAccessFile accessFile = new RandomAccessFile("D:\\test.txt", "rw");
FileChannel fileChannel = accessFile.getChannel();
ByteBuffer buffer = ByteBuffer.allocate(48);
// 将数据从Channel读取到Buffer中,返回读取的字节数
int data = fileChannel.read(buffer);

Buffer(缓冲区)

使用Buffer读取和写入数据通常遵循以下四个步骤:

  1. 将数据写入到缓冲区。

  2. 调用buffer.flip()反转读写模式。

  3. 从缓冲区读取数据。

  4. 调用buffer.clear()或者buffer.compact()清除缓冲区内容。

RandomAccessFile accessFile = new RandomAccessFile("D:\\test.txt", "rw");
FileChannel fileChannel = accessFile.getChannel();
ByteBuffer buffer = ByteBuffer.allocate(48);
// 将数据从Channel读取到Buffer中,返回读取的字节数
int data = fileChannel.read(buffer);
while(data != -1) {
    System.out.println("Read " + data);
    // 将Buffer从写模式切换到读模式
    buffer.flip();
    while(buffer.hasRemaining()) {
        // 每次读取1byte,循环输出 123456789
        System.out.println((char) buffer.get());
    }
    // 清空Buffer,将Buffer从读模式切换到写模式
    buffer.clear();
    data = fileChannel.read(buffer);
}
accessFile.close();java

Channel 通道只负责传输数据、不直接操作数据。操作数据都是通过Buffer缓冲区进行的。通常,通道可以分为两大类:文件通道和套接字通道,

FileChannel:用于文件IO的通道,支持文件的读写等操作。FileChannel允许在文件的任意位置进行数据传输,支持文件锁定以及内存映射文件等高级功能。FileChannel无法设置为非阻塞模式,因为它只适用于阻塞式文件操作。 SocketChannel:用于TCP套接字的IO通信。SocketChannel支持非阻塞模式,可以与Selector一起使用,实现高效的网络通信。Socket Channel允许连接到远程主机,进行数据传输。 与之匹配的有ServerSocketChannel:用于坚挺TCP套接字连接的通道。与SocketChannel类似,ServerSocketChannel也支持非阻塞模式,并可以与Selector一起使用。 DatagramChannel:用于UDP套接字IO通道,支持非阻塞

FileChannel

FileChannel.open(Paths.get("docs/配套教程.md"), StandardOpenOption.WRITE);
  1. 使用FileChannel 配合 ByteBuffer 缓冲区实现文件复制的功能:

try (FileChannel sourceChannel = FileChannel.open(Paths.get("logs/javabetter/itwanger.txt"), StandardOpenOption.READ);
    FileChannel destinationChannel = FileChannel.open(Paths.get("logs/javabetter/itwanger1.txt"), StandardOpenOption.WRITE, StandardOpenOption.CREATE)) {

  ByteBuffer buffer = ByteBuffer.allocate(1024);

  while (sourceChannel.read(buffer) != -1) {
      buffer.flip();
      destinationChannel.write(buffer);
      buffer.clear();
  }
}
  1. 使用内存映射文件(MappedByteBuffer)的方式实现文件复制的功能(直接操作缓冲区):

try (FileChannel sourceChannel = FileChannel.open(Paths.get("logs/javabetter/itwanger.txt"), StandardOpenOption.READ);
      FileChannel destinationChannel = FileChannel.open(Paths.get("logs/javabetter/itwanger2.txt"), StandardOpenOption.WRITE, StandardOpenOption.CREATE, StandardOpenOption.READ)) {

    long fileSize = sourceChannel.size();
    MappedByteBuffer sourceMappedBuffer = sourceChannel.map(FileChannel.MapMode.READ_ONLY, 0, fileSize);
    MappedByteBuffer destinationMappedBuffer = destinationChannel.map(FileChannel.MapMode.READ_WRITE, 0, fileSize);

    for (int i = 0; i < fileSize; i++) {
        byte b = sourceMappedBuffer.get(i);
        destinationMappedBuffer.put(i, b);
    }
}
  1. 通道之间通过transfer()实现数据的传输(直接操作缓冲区):

try (FileChannel sourceChannel = FileChannel.open(Paths.get("logs/javabetter/itwanger.txt"), StandardOpenOption.READ);
      FileChannel destinationChannel = FileChannel.open(Paths.get("logs/javabetter/itwanger3.txt"), StandardOpenOption.WRITE, StandardOpenOption.CREATE, StandardOpenOption.READ)) {
    sourceChannel.transferTo(0, sourceChannel.size(), destinationChannel);
} catch (IOException e) {
    throw new RuntimeException(e);
}
上一页NIO下一页异步文件通道AsynchronousFileChannel

最后更新于1年前

这有帮助吗?