23、Java NIO快速参考指南

Java NIO快速参考指南

1. 简介

Java NIO(New I/O)提供了一组强大的类和接口,用于高效的I/O操作。本指南将对Java NIO中的核心类和接口进行快速参考,涵盖 java.nio java.nio.channels 包中的重要内容。

2. java.nio

java.nio 包包含了用于 java.nio.channels java.nio.charset 子包中的 Buffer 类。

2.1 Buffer

Buffer 是所有其他缓冲区类的基类,包含了所有缓冲区类型通用的方法。以下是 Buffer 类的定义:

public abstract class Buffer {
    public final int capacity()
    public final Buffer clear()
    public final Buffer flip()
    public final boolean hasRemaining()
    public abstract boolean isReadOnly();
    public final int limit()
    public final Buffer limit (int newLimit)
    public final Buffer mark()
    public final int position()
    public final Buffer position (int newPosition)
    public final int remaining()
    public final Buffer reset()
    public final Buffer rewind()
}

2.2 异常类

  • BufferOverflowException :当缓冲区的位置等于其限制时,尝试进行简单的相对 put() 操作,或者批量 put() 操作会导致位置超过限制时,抛出此异常。
public class BufferOverflowException extends RuntimeException {
    public BufferOverflowException()
}
  • BufferUnderflowException :当缓冲区的位置等于其限制时,尝试进行简单的相对 get() 操作,或者批量 get() 操作会导致位置超过限制时,抛出此异常。
public class BufferUnderflowException extends RuntimeException {
    public BufferUnderflowException()
}

2.3 ByteBuffer

ByteBuffer 是所有缓冲区类中最复杂和通用的。只有字节缓冲区可以参与通道上的I/O操作以发送和接收数据。以下是 ByteBuffer 类的部分定义:

public abstract class ByteBuffer extends Buffer implements Comparable {
    public static ByteBuffer allocate (int capacity)
    public static ByteBuffer allocateDirect (int capacity)
    public final byte [] array()
    public final int arrayOffset()
    public abstract CharBuffer asCharBuffer();
    // 其他方法...
}

2.4 ByteOrder

ByteOrder 是一个类型安全的枚举,不能直接实例化。有两个公共可访问的 ByteOrder 实例作为静态类字段可见。提供了一个类方法来确定底层操作系统的本地字节顺序,这可能与Java平台默认的不同。

public final class ByteOrder {
    public static final ByteOrder BIG_ENDIAN
    public static final ByteOrder LITTLE_ENDIAN

    public static ByteOrder nativeOrder()
    public String toString()
}

2.5 其他缓冲区类

除了上述类, java.nio 包中还包含了 CharBuffer DoubleBuffer FloatBuffer IntBuffer LongBuffer ShortBuffer 等类,它们分别管理不同类型的数据元素。以下是 CharBuffer 类的部分定义:

public abstract class CharBuffer extends Buffer implements Comparable, CharSequence {
    public static CharBuffer allocate (int capacity)
    public final char [] array()
    public final int arrayOffset()
    public abstract CharBuffer asReadOnlyBuffer();
    // 其他方法...
}

2.6 异常类

  • InvalidMarkException :当在没有设置标记的缓冲区上调用 reset() 方法时,抛出此异常。
public class InvalidMarkException extends IllegalStateException {
    public InvalidMarkException()
}
  • ReadOnlyBufferException :当在只读缓冲区上调用会修改缓冲区内容的方法(如 put() compact() )时,抛出此异常。
public class ReadOnlyBufferException extends UnsupportedOperationException {
    public ReadOnlyBufferException()
}

2.7 MappedByteBuffer

MappedByteBuffer 是一种特殊类型的 ByteBuffer ,其数据元素是磁盘文件的内容。只能通过调用 FileChannel 对象的 map() 方法来创建 MappedByteBuffer 对象。

public abstract class MappedByteBuffer extends ByteBuffer {
    public final MappedByteBuffer force()
    public final boolean isLoaded()
    public final MappedByteBuffer load()
}

3. java.nio.channels

java.nio.channels 包包含了与通道和选择器相关的类和接口。

3.1 异常类

  • AlreadyConnectedException :当在已经连接的 SocketChannel 对象上调用 connect() 方法时,抛出此异常。
public class AlreadyConnectedException extends IllegalStateException {
    public AlreadyConnectedException()
}
  • AsynchronousCloseException :当一个线程在通道操作(如 read() write() )上被阻塞,而另一个线程关闭了该通道时,抛出此异常。
public class AsynchronousCloseException extends ClosedChannelException {
    public AsynchronousCloseException()
}

3.2 接口类

  • ByteChannel :这是一个空的聚合接口,将 ReadableByteChannel WritableByteChannel 组合成一个单一的接口,但不定义任何新方法。
public interface ByteChannel extends ReadableByteChannel, WritableByteChannel {
}
  • Channel :是所有其他通道接口的超接口,定义了所有具体通道类通用的方法。
public interface Channel {
    public void close() throws java.io.IOException;
    public boolean isOpen();
}

3.3 Channels 工具类

Channels 是一个实用类,使通道能够与传统的字节和字符流进行互操作。工厂方法返回包装对象,使通道适应流,反之亦然。返回的通道对象可能不可选择或不可中断。

public final class Channels {
    public static ReadableByteChannel newChannel (java.io.InputStream in)
    public static WritableByteChannel newChannel (java.io.OutputStream out)
    public static java.io.InputStream newInputStream (ReadableByteChannel ch)
    public static java.io.OutputStream newOutputStream (WritableByteChannel ch)
    public static java.io.Reader newReader (ReadableByteChannel ch, String csName)
    public static java.io.Reader newReader (ReadableByteChannel ch, java.nio.charset.CharsetDecoder dec, int minBufferCap)
    public static java.io.Writer newWriter (WritableByteChannel ch, String csName)
    public static java.io.Writer newWriter (WritableByteChannel ch, java.nio.charset.CharsetEncoder enc, int minBufferCap)
}

3.4 其他异常类

  • CancelledKeyException :当尝试使用已失效的 SelectionKey 对象时,抛出此异常。
public class CancelledKeyException extends IllegalStateException {
    public CancelledKeyException()
}
  • ClosedByInterruptException :当一个线程在通道操作(如 read() write() )上被阻塞,而另一个线程中断了该线程时,抛出此异常。作为副作用,该线程正在休眠的通道将被关闭。
public class ClosedByInterruptException extends AsynchronousCloseException {
    public ClosedByInterruptException()
}
  • ClosedChannelException :当尝试对已关闭的通道进行操作时,抛出此异常。
public class ClosedChannelException extends java.io.IOException {
    public ClosedChannelException()
}
  • ClosedSelectorException :当尝试使用已关闭的 Selector 时,抛出此异常。
public class ClosedSelectorException extends IllegalStateException {
    public ClosedSelectorException()
}
  • ConnectionPendingException :当在非阻塞模式的 SocketChannel 对象上调用 connect() 方法,而该对象已经有一个并发连接正在进行时,抛出此异常。
public class ConnectionPendingException extends IllegalStateException {
    public ConnectionPendingException()
}

3.5 DatagramChannel

DatagramChannel 类提供了从 ByteBuffer 对象发送和接收数据报包的方法。

public abstract class DatagramChannel extends java.nio.channels.spi.AbstractSelectableChannel implements ByteChannel, ScatteringByteChannel, GatheringByteChannel {
    public abstract DatagramChannel connect (java.net.SocketAddress remote) throws java.io.IOException;
    public abstract DatagramChannel disconnect() throws java.io.IOException;
    public abstract boolean isConnected();
    public static DatagramChannel open() throws java.io.IOException
    public abstract int read (java.nio.ByteBuffer dst) throws java.io.IOException;
    public final long read (java.nio.ByteBuffer [] dsts) throws java.io.IOException
    public abstract long read (java.nio.ByteBuffer [] dsts, int offset, int length) throws java.io.IOException;
    public abstract java.net.SocketAddress receive (java.nio.ByteBuffer dst) throws java.io.IOException;
    public abstract int send (java.nio.ByteBuffer src, java.net.SocketAddress target) throws java.io.IOException;
    public abstract java.net.DatagramSocket socket();
    public final int validOps()
    public abstract int write (java.nio.ByteBuffer src) throws java.io.IOException;
    public final long write (java.nio.ByteBuffer [] srcs) throws java.io.IOException
    public abstract long write (java.nio.ByteBuffer [] srcs, int offset, int length) throws java.io.IOException;
}

3.6 FileChannel

FileChannel 类提供了丰富的文件操作。只能通过在 RandomAccessFile FileInputStream FileOutputStream 对象上调用 getChannel() 方法来获取 FileChannel 对象。

public abstract class FileChannel extends java.nio.channels.spi.AbstractInterruptibleChannel implements ByteChannel, GatheringByteChannel, ScatteringByteChannel {
    public abstract void force (boolean metaData) throws java.io.IOException;
    public final FileLock lock() throws java.io.IOException
    public abstract FileLock lock (long position, long size, boolean shared) throws java.io.IOException;
    public abstract java.nio.MappedByteBuffer map (FileChannel.MapMode mode, long position, long size) throws java.io.IOException;
    public abstract long position() throws java.io.IOException;
    public abstract FileChannel position (long newPosition) throws java.io.IOException;
    public abstract int read (java.nio.ByteBuffer dst) throws java.io.IOException;
    public final long read (java.nio.ByteBuffer [] dsts) throws java.io.IOException
    public abstract int read (java.nio.ByteBuffer dst, long position) throws java.io.IOException;
    public abstract long read (java.nio.ByteBuffer [] dsts, int offset, int length) throws java.io.IOException;
    public abstract long size() throws java.io.IOException;
    public abstract long transferFrom (ReadableByteChannel src, long position, long count) throws java.io.IOException;
    public abstract long transferTo (long position, long count, WritableByteChannel target) throws java.io.IOException;
    public abstract FileChannel truncate (long size) throws java.io.IOException;
    public final FileLock tryLock() throws java.io.IOException
    public abstract FileLock tryLock (long position, long size, boolean shared) throws java.io.IOException;
    public abstract int write (java.nio.ByteBuffer src) throws java.io.IOException;
    public final long write (java.nio.ByteBuffer [] srcs) throws java.io.IOException
    public abstract int write (java.nio.ByteBuffer src, long position) throws java.io.IOException;
    public abstract long write (java.nio.ByteBuffer [] srcs, int offset, int length) throws java.io.IOException;

    public static class FileChannel.MapMode {
        public static final FileChannel.MapMode PRIVATE
        public static final FileChannel.MapMode READ_ONLY
        public static final FileChannel.MapMode READ_WRITE

        public String toString()
    }
}

3.7 FileLock

FileLock 类封装了与 FileChannel 对象关联的锁区域。

public abstract class FileLock {
    public final FileChannel channel()
    public final boolean isShared()
    public abstract boolean isValid();
    public final boolean overlaps (long position, long size)
    public final long position()
    public abstract void release() throws java.io.IOException;
    public final long size()
    public final String toString()
}

总结

本部分介绍了 java.nio java.nio.channels 包中的核心类和接口,包括缓冲区类、通道类、异常类等。这些类和接口为Java中的高效I/O操作提供了强大的支持。通过合理使用这些类和接口,可以实现更高效、更灵活的I/O编程。

流程图

graph TD;
    A[java.nio包] --> B[Buffer类];
    A --> C[ByteBuffer类];
    A --> D[ByteOrder类];
    A --> E[其他缓冲区类];
    A --> F[异常类];
    A --> G[MappedByteBuffer类];
    H[java.nio.channels包] --> I[异常类];
    H --> J[接口类];
    H --> K[Channels工具类];
    H --> L[其他异常类];
    H --> M[DatagramChannel类];
    H --> N[FileChannel类];
    H --> O[FileLock类];

表格

包名 类名 描述
java.nio Buffer 所有缓冲区类的基类
java.nio ByteBuffer 最复杂和通用的缓冲区类,可参与I/O操作
java.nio ByteOrder 类型安全的枚举,用于确定字节顺序
java.nio.channels DatagramChannel 用于发送和接收数据报包
java.nio.channels FileChannel 提供丰富的文件操作

3.8 各异常类及相关类的关系总结

为了更清晰地理解 java.nio.channels 包中各异常类以及相关类之间的关系,我们可以通过以下表格和流程图进行总结。

异常类/相关类 父类/接口 触发条件
AlreadyConnectedException IllegalStateException 在已连接的 SocketChannel 对象上调用 connect() 方法
AsynchronousCloseException ClosedChannelException 线程在通道操作被阻塞时,通道被其他线程关闭
CancelledKeyException IllegalStateException 尝试使用已失效的 SelectionKey 对象
ClosedByInterruptException AsynchronousCloseException 线程在通道操作被阻塞时,被其他线程中断
ClosedChannelException IOException 尝试对已关闭的通道进行操作
ClosedSelectorException IllegalStateException 尝试使用已关闭的 Selector
ConnectionPendingException IllegalStateException 在非阻塞模式的 SocketChannel 对象上调用 connect() ,且已有并发连接在进行
graph TD;
    A[IOException] --> B[ClosedChannelException];
    B --> C[AsynchronousCloseException];
    C --> D[ClosedByInterruptException];
    E[IllegalStateException] --> F[AlreadyConnectedException];
    E --> G[CancelledKeyException];
    E --> H[ClosedSelectorException];
    E --> I[ConnectionPendingException];
    J[Channel] --> K[SocketChannel];
    K --> F;
    K --> I;
    L[SelectionKey] --> G;
    M[Selector] --> H;
    N[AbstractSelectableChannel] --> O[DatagramChannel];
    P[AbstractInterruptibleChannel] --> Q[FileChannel];

4. 操作示例

4.1 ByteBuffer 的使用示例

以下是一个简单的 ByteBuffer 使用示例,展示了如何分配缓冲区、写入数据和读取数据。

import java.nio.ByteBuffer;

public class ByteBufferExample {
    public static void main(String[] args) {
        // 分配一个容量为10的ByteBuffer
        ByteBuffer buffer = ByteBuffer.allocate(10);

        // 写入数据
        buffer.put((byte) 1);
        buffer.put((byte) 2);
        buffer.put((byte) 3);

        // 切换到读模式
        buffer.flip();

        // 读取数据
        while (buffer.hasRemaining()) {
            System.out.println(buffer.get());
        }
    }
}
4.2 FileChannel 的使用示例

以下示例展示了如何使用 FileChannel 读取文件内容。

import java.io.FileInputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;

public class FileChannelExample {
    public static void main(String[] args) {
        try (FileInputStream fis = new FileInputStream("test.txt");
             FileChannel channel = fis.getChannel()) {
            // 分配一个容量为1024的ByteBuffer
            ByteBuffer buffer = ByteBuffer.allocate(1024);

            // 读取数据到缓冲区
            int bytesRead = channel.read(buffer);
            while (bytesRead != -1) {
                // 切换到读模式
                buffer.flip();

                // 处理缓冲区中的数据
                while (buffer.hasRemaining()) {
                    System.out.print((char) buffer.get());
                }

                // 清空缓冲区
                buffer.clear();
                bytesRead = channel.read(buffer);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

5. 总结与展望

Java NIO提供的类和接口为高效的I/O操作提供了强大的支持。 java.nio 包中的缓冲区类可以帮助我们更好地管理数据,而 java.nio.channels 包中的通道类和选择器类则为非阻塞I/O操作提供了可能。

通过合理使用这些类和接口,我们可以实现更高效、更灵活的I/O编程。例如,在网络编程中,可以使用 DatagramChannel SocketChannel 进行数据的发送和接收;在文件操作中,可以使用 FileChannel 进行文件的读写和锁定。

未来,随着技术的不断发展,Java NIO可能会进一步优化和扩展,以满足更多的应用场景需求。例如,可能会提供更高效的缓冲区管理机制,或者支持更多类型的通道操作。开发者可以持续关注Java NIO的发展,以便在实际项目中更好地应用这些技术。

流程图

graph TD;
    A[操作示例] --> B[ByteBuffer示例];
    A --> C[FileChannel示例];
    B --> D[分配缓冲区];
    B --> E[写入数据];
    B --> F[切换到读模式];
    B --> G[读取数据];
    C --> H[创建FileInputStream];
    H --> I[获取FileChannel];
    I --> J[分配ByteBuffer];
    J --> K[读取数据到缓冲区];
    K --> L[切换到读模式];
    L --> M[处理数据];
    M --> N[清空缓冲区];
    N --> K;

表格

操作示例 步骤 代码片段
ByteBuffer示例 分配缓冲区 ByteBuffer buffer = ByteBuffer.allocate(10);
ByteBuffer示例 写入数据 buffer.put((byte) 1);
ByteBuffer示例 切换到读模式 buffer.flip();
ByteBuffer示例 读取数据 buffer.get();
FileChannel示例 创建FileInputStream FileInputStream fis = new FileInputStream("test.txt");
FileChannel示例 获取FileChannel FileChannel channel = fis.getChannel();
FileChannel示例 分配ByteBuffer ByteBuffer buffer = ByteBuffer.allocate(1024);
FileChannel示例 读取数据到缓冲区 int bytesRead = channel.read(buffer);
FileChannel示例 切换到读模式 buffer.flip();
FileChannel示例 处理数据 System.out.print((char) buffer.get());
FileChannel示例 清空缓冲区 buffer.clear();
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值