Java NIO
1.BIO与NIO的区别
BIO为阻塞IO,NIO为非阻塞IO。
BIO | NIO |
---|---|
JAVA1.4之前 | Java 1.4之后 |
面向流:以byte为单位处理数据 | 面向块:以块为单位处理数据 |
同步阻塞 | 同步非阻塞 |
无 | 选择器(Selector) |
1.1NIO的核心组成部分
- Channels
Channel是双向的,既能做读操作也能做写操作,常见Channel如下:
Channel类 | 功能 |
---|---|
FileChannel | 文件数据读写 |
DtagramChannel | UDP数据读写 |
ServerScoketChannel和SocketChannel | TCP数据读写 |
- Buffers
缓冲区 - Selectors
选择器,用于监听多个通道的事件,可实现单个线程就可以监听多个客户端通道。
2.Channel
Channel封装了对数据源的操作,可以操作多种数据源,但是不必关心数据源的具体物理结构。Channel用于在字节缓冲区和另一侧的实体之间有效地传输数据。
Channel所有数据都是通过Buffer对象进行处理,通道要么读数据到缓冲区,要么从缓冲区写入到通道。
public interface Channle extend Closeable {
public boolean isOpen();
public void close() throws IOException;
}
2.1 FileChannel
FileChannel常用方法如下;
方法名 | 作用 |
---|---|
public int read(ByteBuffer dst) | 从通道读取数据并放到缓冲区中 |
public int write(ByteBuffer src) | 把缓冲区的数据写到通道中 |
public long transferFrom(ReadableByteChannel src, long position, long count) | 从目标通道中复制数据到当前通道 |
public long transferTo(long position, long count, WritableByteChannel target) | 把数据从当前通道复制给目标通道 |
无法直接打开一个FileChannel,常见的方法是通过inPutStream和outPutStream或RandomAccessFile获取一个FileChannel实例。
示例代码
文件写入示例
package com.hero.nio.file;
import org.junit.Test;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
//通过NIO实现文件IO
public class TestNIO {
@Test //往本地文件中写数据
public void test1() throws Exception{
//1. 创建输出流
FileOutputStream fos=new FileOutputStream("basic.txt");
//2. 从流中得到一个通道
FileChannel fc=fos.getChannel();
//3. 提供一个缓冲区
ByteBuffer buffer=ByteBuffer.allocate(1024);
//4. 往缓冲区中存入数据
String str="HelloJava";
buffer.put(str.getBytes());
//5. 翻转缓冲区
buffer.flip();
while(buffer.hasRemaining()) {
//6. 把缓冲区写到通道中
fc.write(buffer);
}
//7. 关闭
fos.close();
}
}
文件复制示例
public void test4() throws Exception {
//1. 创建两个流
FileInputStream fis = new FileInputStream("basic2.txt");
FileOutputStream fos = new FileOutputStream("basic3.txt");
//2. 得到两个通道
FileChannel sourceFC = fis.getChannel();
FileChannel destFC = fos.getChannel();
//3. 复制
destFC.transferFrom(sourceFC, 0, sourceFC.size());
//4. 关闭
fis.close();
fos.close();
}