什么是NIO?
JDK1.4版本开始,JDK提供了新的IO操作API, NIO提供多路(non-blocking) 非阻塞式的高伸缩性网络I/O,从而提高了效率,NIO主要有三大核心组件:Channel、Buffer和Selector。
Buffer:
1、Buffer是一个抽象类,Buffer类型变量对应的对象代表一块缓冲区,ByteBuffer、CharBuffer、DoubleBuffer、FloatBuffer、IntBuffer、LongBuffer和ShortBuffer类都是Buffer抽象类的子类,其中ByteBuffer最常用。
2、ByteBuffer常用方法:
方法 | 作用 |
---|---|
allocate(int capacity) | 分配一个新的字节缓冲区。 |
capacity() | 返回此缓冲区的容量。 |
put(byte b) | 将字节类型数据写入当前位置的缓冲区,然后当前位置+1,位置从0开始。 |
array() | 将ByteBuffer类型的数据转为byte数组。 |
position() | 返回缓冲区当前位置。 |
flip() | 翻转缓冲区,将position置零。 |
hasRemaining() | 判断当前位置后面是否有位置。即距最大容量处还有位置返回true。 |
get() | 读取缓冲区当前位置的字节,然后当前位置+1。 |
clear() | 清除此缓冲区。 位置设置为零,限制设置为容量,标记被丢弃。 在使用一系列通道读取或放置操作填充此缓冲区之前调用此方法。这个方法实际上并不会清除缓冲区中的数据。 |
import java.nio.ByteBuffer;
public class Test {
public static void main(String[] args){
ByteBuffer buffer = ByteBuffer.allocate(2);
System.out.println("容量为:"+buffer.capacity()); //容量为2。
byte a = 1;
buffer.put(a);
System.out.println("当前位置为:"+buffer.position()); //put后位置加一。
System.out.println("当前位置的字节为:"+buffer.get()); //a字节在0位置,1位置没有字节,所以为0。且get后位置加一。
System.out.println("当前位置为:"+buffer.position()); //此时为2。
System.out.println("hasRemaining()的结果为:"+buffer.hasRemaining()); //没有剩余位置,返回false。
buffer.flip();
System.out.println("flip后当前位置为:"+buffer.position()); //位置重置为0。
byte[] b = buffer.array();
for (byte c : b) {
System.out.println(c); //输出数组内容。
}
}
}
输出:
容量为:2
当前位置为:1
当前位置的字节为:0
当前位置为:2
hasRemaining()的结果为:false
flip后当前位置为:0
1
0
Channel:
1、Channel是一个接口,该接口类型变量指向的对象代表一个数据传输通道,Channel对象是面向缓冲区的:数据总是从通道读取到缓冲区(Buffer类型对象),或从缓冲区(Buffer类型对象)写入到通道中。
Channel接口主要实现类如下:
① FileChannel:从文件中读写数据。
② DatagramChannel:通过UDP读写网络中的数据。
③ SocketChannel:通过TCP读写网络中的数据。
④ ServerSocketChannel:可以监听新进来的TCP连接,像Web服务器那样,对每一个新进来的连接都会创建一个SocketChannel。
2、FileChannel:
只能通过调用FileInputStream和FileOutputStream类中getChannel方法获取FileChannel对象,FileChannel类常用方法如下:
方法 | 作用 |
---|---|
read(ByteBuffer dst) | 从通道的当前文件位置开始将数据读取到缓冲区,然后以实际读取的字节数更新文件位置;返回实际读取的字节数,如果已达到通道末尾, 则返回-1 。 |
close() | 关闭通道。 |
write(ByteBuffer src) | 从通道的当前文件位置开始将缓冲区中数据写入通道,然后文件位置用实际写入的字节数更新。 |
文件输入到程序:
import java.io.FileInputStream;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
public class Test {
public static void main(String[] args){
FileInputStream fileInputStream;
try {
fileInputStream = new FileInputStream("D:\\1.txt");
FileChannel fileChannel = fileInputStream.getChannel();
ByteBuffer buffer = ByteBuffer.allocate(1024);
while(fileChannel.read(buffer)!=-1) //将1024字节的数据缓存读到通道。
{
buffer.flip(); //位置重置0。
String result = new String(buffer.array()); //将buffer缓存内容转化为byte[]数组,在输出成String类型。
System.out.println(result);
buffer.clear();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
文件复制:
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
public class Test {
public static void main(String[] args){
try {
FileInputStream fileInputStream = new FileInputStream("C:\\1.png");
FileOutputStream fileOutputStream = new FileOutputStream("C:\\2.png");
FileChannel inputChannel = fileInputStream.getChannel(); //输入通道。
FileChannel outputChannel = fileOutputStream.getChannel(); //输出通道。
ByteBuffer buffer = ByteBuffer.allocate(1024); //设置缓存大小。
while(inputChannel.read(buffer)!=-1)
{
buffer.flip(); //位置重置为0.
outputChannel.write(buffer); //从0位置读取文件。
buffer.clear(); //读取前用clear调整位置。
}
} catch (Exception e) {
e.printStackTrace();
}
}
}