1. NIO的基本概念
Java NIO 是由Java 1.4引入的异步IO,由主要由以下几个部分组成:Buffer,Channel,Selector
.Java NIO跟传统的IO的区别?
传统的IO是面向Stream(流),NIO是基于Buffer(缓冲区)
IO操作是阻塞的,NIO是非阻塞的。
IO操作中没有Selector概念,而NIO中有Selector概念。
2. NIO Buffer
1. NIO中Buffer的种类:
ByteBuffer、MappedByteBuffer、CharBuffer、DoubleBuffer、FloatBuffer、IntBuffer、LongBuffer、ShortBuffer.
2. NIO中Buffer的基本使用步骤:
- 写入数据到Buffer
- 调用
flip()
方法 - 从Buffer中读取数据
- 调用
clear()
方法或者compact()
方法
public static void main(String[] args) {
// 分配内存
IntBuffer intBuffer = IntBuffer.allocate(20);
// 写入数据
intBuffer.put(12313);
intBuffer.put(1);
// position 变为 0,capacity不变,为20,limit和capacity一样,都是20
System.out.println("position = " + intBuffer.position()+",capacity = " + intBuffer.capacity()+",limit = " + intBuffer.limit());
// 写模式转换为读模式
intBuffer.flip();
// position 变为 0,capacity不变,为20,limit变为2
System.out.println("position = " + intBuffer.position()+",capacity = " + intBuffer.capacity()+",limit = " + intBuffer.limit());
// 获取数据
System.out.println(intBuffer.get());
System.out.println(intBuffer.get());
// position 变为 2,capacity不变,limit变为2
System.out.println("position = " + intBuffer.position()+",capacity = " + intBuffer.capacity()+",limit = " + intBuffer.limit());
}
3. ByteBuf的核心属性(图片来源,并发编程网):
capacity: buffer的大小。
position:当你写数据到Buffer中时,position表示当前的位置。初始的position值为0.当一个byte、long等数据写到Buffer后, position会向前移动到下一个可插入数据的Buffer单元。position最大可为capacity – 1.当读取数据时,也是从某个特定位置读。当将Buffer从写模式切换到读模式,position会被重置为0. 当从Buffer的position处读取数据时,position向前移动到下一个可读的位置。
limit:在写模式下,limit等于Buffer的capacity。在读模式下, limit表示你最多能读到多少数据。
3. NIO Channel
1. Channel的类型:FileChannel,SocketChannel,ServerSocketChannel,DatagramChannel.
2. FileChannel的基本使用方法:
public static void main(String[] args) throws IOException {
RandomAccessFile randomAccessFile = new RandomAccessFile("C:\\Users\\Administrator\\Desktop\\1.txt", "rw");
FileChannel fileChannel = randomAccessFile.getChannel();
ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
byte[] bytes = new byte[1024];
int byteBufferSize = fileChannel.read(byteBuffer);
while (byteBufferSize != -1) {
// 从读取模式切换到写模式
byteBuffer.flip();
// 一次性读取所有内容
bytes = byteBuffer.array();
System.out.println(new String(bytes, Charset.forName("UTF-8")));
// 一个字符一个字符的读,
// while (byteBuffer.hasRemaining()) {
// System.out.println((char) byteBuffer.get());
// // java 中一个char是两个字节
// // System.out.println(byteBuffer.getChar());
// }
// 清空byteBuffer,并从读模式切换到写模式
byteBuffer.clear();
byteBufferSize = fileChannel.read(byteBuffer);
}
fileChannel.close(); // 关闭channel
}
写入数据:
public static void writeData() throws IOException{
RandomAccessFile randomAccessFile = new RandomAccessFile("C:\\Users\\Administrator\\Desktop\\1.txt", "rw");
FileChannel fileChannel = randomAccessFile.getChannel();
String newData = "New String to write to file..." + System.currentTimeMillis();
ByteBuffer buf = ByteBuffer.allocate(48);
buf.clear();
buf.put(newData.getBytes());
buf.flip();
while(buf.hasRemaining()) {
fileChannel.write(buf);
}
fileChannel.close();
}