前言
JDK 1.4 后, Java 提供了一个全新的 IO API, 即 Java New IO
本文 全面 & 详细解析 Java New IO, 希望你们会喜欢
目录
示意图
储备知识: Java IO
示意图
1. 定义
即 Java New IO
是 1 个全新的, JDK 1.4 后提供的 IO API
2. 作用
提供了与标准 IO 不同的 IO 工作方式
可替代 标准 Java IO 的 IO API
3. 新特性
对比于 Java IO,NIO 具备的新特性如下
示意图
4. 核心组件
Java NIO 的核心组件 包括:
通道 (Channel)
缓冲区 (Buffer)
选择器 (Selectors)
下面将详细介绍:
示意图
5. 具体使用
5.1 基于通道 & 缓冲数据
具体步骤如下:
- // 1. 获取数据源 和 目标传输地的输入输出流 (此处以数据源 = 文件为例)
- FileInputStream fin = new FileInputStream(infile);
- FileOutputStream fout = new FileOutputStream(outfile);
- // 2. 获取数据源的输入输出通道
- FileChannel fcin = fin.getChannel();
- FileChannel fcout = fout.getChannel();
- // 3. 创建 缓冲区 对象: Buffer(共有 2 种方法)
- // 方法 1: 使用 allocate() 静态方法
- ByteBuffer buff = ByteBuffer.allocate(256);
- // 上述方法创建 1 个容量为 256 字节的 ByteBuffer
- // 注: 若发现创建的缓冲区容量太小, 则重新创建一个大小合适的缓冲区
- // 方法 2: 通过包装一个已有的数组来创建
- // 注: 通过包装的方法创建的缓冲区保留了被包装数组内保存的数据
- ByteBuffer buff = ByteBuffer.wrap(byteArray);
- // 额外: 若需将 1 个字符串存入 ByteBuffer, 则如下
- String sendString="你好, 服务器.";
- ByteBuffer sendBuff = ByteBuffer.wrap(sendString.getBytes("UTF-16"));
- // 4. 从通道读取数据 & 写入到缓冲区
- // 注: 若 以读取到该通道数据的末尾, 则返回 - 1
- fcin.read(buff);
- // 5. 传出数据准备: 将缓存区的写模式 转换 ->> 读模式
- buff.flip();
- // 6. 从 Buffer 中读取数据 & 传出数据到通道
- fcout.write(buff);
- // 7. 重置缓冲区
- // 目的: 重用现在的缓冲区, 即 不必为了每次读写都创建新的缓冲区, 在再次读取之前要重置缓冲区
- // 注: 不会改变缓冲区的数据, 只是重置缓冲区的主要索引值
- buff.clear();
5.2 基于选择器 (Selecter)
具体步骤如下:
- // 1. 创建 Selector 对象
- Selector sel = Selector.open();
- // 2. 向 Selector 对象绑定通道
- // a. 创建可选择通道, 并配置为非阻塞模式
- ServerSocketChannel server = ServerSocketChannel.open();
- server.configureBlocking(false);
- // b. 绑定通道到指定端口
- ServerSocket socket = server.socket();
- InetSocketAddress address = new InetSocketAddress(port);
- socket.bind(address);
- // c. 向 Selector 中注册感兴趣的事件
- server.register(sel, SelectionKey.OP_ACCEPT);
- return sel;
- // 3. 处理事件
- try {
- while(true) {
- // 该调用会阻塞, 直到至少有一个事件就绪, 准备发生
- selector.select();
- // 一旦上述方法返回, 线程就可以处理这些事件
- Set<SelectionKey> keys = selector.selectedKeys();
- Iterator<SelectionKey> iter = keys.iterator();
- while (iter.hasNext()) {
- SelectionKey key = (SelectionKey) iter.next();
- iter.remove();
- process(key);
- }
- }
- } catch (IOException e) {
- e.printStackTrace();
- }
6. 实例讲解
实例说明: 实现文件复制功能
实现方式: 通道 FileChannel, 缓冲区 ByteBuffer
- import java.io.FileInputStream;
- import java.io.FileOutputStream;
- import java.io.IOException;
- import java.nio.ByteBuffer;
- import java.nio.channels.FileChannel;
- public class Test {
- public static void main(String[] args) throws IOException {
- // 设置输入源 & 输出地 = 文件
- String infile = "C:\\copy.sql";
- String outfile = "C:\\copy.txt";
- // 1. 获取数据源 和 目标传输地的输入输出流 (此处以数据源 = 文件为例)
- FileInputStream fin = new FileInputStream(infile);
- FileOutputStream fout = new FileOutputStream(outfile);
- // 2. 获取数据源的输入输出通道
- FileChannel fcin = fin.getChannel();
- FileChannel fcout = fout.getChannel();
- // 3. 创建缓冲区对象
- ByteBuffer buff = ByteBuffer.allocate(1024);
- while (true) {
- // 4. 从通道读取数据 & 写入到缓冲区
- // 注: 若 以读取到该通道数据的末尾, 则返回 - 1
- int r = fcin.read(buff);
- if (r == -1) {
- break;
- }
- // 5. 传出数据准备: 调用 flip() 方法
- buff.flip();
- // 6. 从 Buffer 中读取数据 & 传出数据到通道
- fcout.write(buff);
- // 7. 重置缓冲区
- buff.clear();
- }
- }
- }
7. 与 Java IO 的区别
示意图
8. 总结
本文全面讲解了 Java 中的 NIO 的相关知识
下面我将继续对 Android & Java 中的知识进行深入讲解 , 有兴趣可以继续关注 Carson_Ho 的安卓开发笔记
请点赞! 因为你的鼓励是我写作的最大动力!
来源: http://www.jianshu.com/p/d30893c4d6bb