NIO

Java NIO简介

Java NIO(New IO Non Blocking IO)是从Java1.4版本开始引入的一个新的IO API,可以替代标准的JJava IO API。NIO与原来的IO有同样的作用和目的,但是使用的方式完全不同,NIO支持面向缓存区的、基于通道的IO操作。NIO将以更加高效的方式进行文件的读写操作。

Java NIO与IO的主要区别

传统的IO
在这里插入图片描述
NIO
在这里插入图片描述
Java NIO系统的核心在于:通道(Channel)和缓冲区(Buffer)。通道表示打开到IO设备(例如:文件、套接字)的连接。若需要使用NIO系统,需要获取用于连接。若需要使用NIO系统,需要获取用于连接IO设备的通道以及用于容纳数据的缓冲区。然后操作缓冲区,对数据进行处理。

在这里插入图片描述

缓冲区(Buffer)和通道(Channel)

缓冲区(Buffer)

一、缓冲区(Buffer):在JAVA的nio中 负责数据的存取。缓存区就是数组。用于存储不同数据类型的数据。

根据数据类型不同(boolean除外),提供了相应类型的缓冲区:

  • ByteBuffer
  • CharBuffer
  • ShortBuffer
  • IntBuffer
  • LongBuffer
  • FloatBuffer
  • DoubleBuffer

上述缓冲区的管理方式几乎一致,通过allocate()获取缓冲区

二、缓冲区存取数据的两个核心方法

  • put() : 存入数据到缓冲区中
  • get() : 获取缓冲区中的数据

三、缓冲区中的四个核心属性

  • capacity: 容量,表示缓冲区中最大存储数据的容量。一旦声明不能改变。
  • limit: 界限,表示缓冲区中可以操作数据的大小。(limit后数据不能进行读写)
  • position: 位置,表示缓冲区中正在操作数据的位置

position <= limit <= capacity
原码:
在这里插入图片描述
在这里插入图片描述

1.分配一个指定大小的缓冲区
package com.nio.test;

import java.nio.ByteBuffer;

import org.junit.Test;

/**
 * 一、缓冲区(Buffer):在JAVA的nio中 负责数据的存取。缓存区就是数组。用于存储不同数据类型的数据。
 * 
 * 根据数据类型不同(boolean除外),提供了相应类型的缓冲区:
 * ByteBuffer
 * CharBuffer
 * ShortBuffer
 * IntBuffer
 * LongBuffer
 * FloatBuffer
 * DoubleBuffer
 * 
 * 上述缓冲区的管理方式几乎一致,通过allocate()获取缓冲区
 * 
 * 二、缓冲区存取数据的两个核心方法
 * put() : 存入数据到缓冲区中
 * get() : 获取缓冲区中的数据
 * 
 * 三、缓冲区中的四个核心属性
 * capacity: 容量,表示缓冲区中最大存储数据的容量。一旦声明不能改变。
 * limit: 界限,表示缓冲区中可以操作数据的大小。(limit后数据不能进行读写)
 * position: 位置,表示缓冲区中正在操作数据的位置
 * position <= limit <= capacity
 * 
 */
public class TestBuffer {

	//创建一个缓冲区
	@Test
	public void test1() {
		//1.分配一个指定大小的缓冲区
		ByteBuffer buf = ByteBuffer.allocate(1024);
		System.out.println("---------------allocate()-----------------");
		System.out.println("position:"+buf.position());
		System.out.println("limit:"+buf.limit());
		System.out.println("capacity:"+buf.capacity());
	}
}

在这里插入图片描述

2.利用put()存入数据到缓冲区中
package com.nio.test;

import java.nio.ByteBuffer;

import org.junit.Test;

/**
 * 一、缓冲区(Buffer):在JAVA的nio中 负责数据的存取。缓存区就是数组。用于存储不同数据类型的数据。
 * 
 * 根据数据类型不同(boolean除外),提供了相应类型的缓冲区:
 * ByteBuffer
 * CharBuffer
 * ShortBuffer
 * IntBuffer
 * LongBuffer
 * FloatBuffer
 * DoubleBuffer
 * 
 * 上述缓冲区的管理方式几乎一致,通过allocate()获取缓冲区
 * 
 * 二、缓冲区存取数据的两个核心方法
 * put() : 存入数据到缓冲区中
 * get() : 获取缓冲区中的数据
 * 
 * 三、缓冲区中的四个核心属性
 * capacity: 容量,表示缓冲区中最大存储数据的容量。一旦声明不能改变。
 * limit: 界限,表示缓冲区中可以操作数据的大小。(limit后数据不能进行读写)
 * position: 位置,表示缓冲区中正在操作数据的位置
 * position <= limit <= capacity
 * 
 */
public class TestBuffer {

	//创建一个缓冲区
	@Test
	public void test1() {
		String str = "abcde";
		
		//1.分配一个指定大小的缓冲区
		ByteBuffer buf = ByteBuffer.allocate(1024);
		System.out.println("---------------allocate()-----------------");
		System.out.println("position:"+buf.position());
		System.out.println("limit:"+buf.limit());
		System.out.println("capacity:"+buf.capacity());
		
		//2.利用put()存入数据到缓冲区中
		buf.put(str.getBytes());
		System.out.println("---------------put()-----------------");
		System.out.println("position:"+buf.position());
		System.out.println("limit:"+buf.limit());
		System.out.println("capacity:"+buf.capacity());
	}
}

在这里插入图片描述

3.切换读取数据模式,利用flip()
package com.nio.test;

import java.nio.Buffer;
import java.nio.ByteBuffer;

import org.junit.Test;

/**
 * 一、缓冲区(Buffer):在JAVA的nio中 负责数据的存取。缓存区就是数组。用于存储不同数据类型的数据。
 * 
 * 根据数据类型不同(boolean除外),提供了相应类型的缓冲区:
 * ByteBuffer
 * CharBuffer
 * ShortBuffer
 * IntBuffer
 * LongBuffer
 * FloatBuffer
 * DoubleBuffer
 * 
 * 上述缓冲区的管理方式几乎一致,通过allocate()获取缓冲区
 * 
 * 二、缓冲区存取数据的两个核心方法
 * put() : 存入数据到缓冲区中
 * get() : 获取缓冲区中的数据
 * 
 * 三、缓冲区中的四个核心属性
 * capacity: 容量,表示缓冲区中最大存储数据的容量。一旦声明不能改变。
 * limit: 界限,表示缓冲区中可以操作数据的大小。(limit后数据不能进行读写)
 * position: 位置,表示缓冲区中正在操作数据的位置
 * position <= limit <= capacity
 * 
 */
public class TestBuffer {

	//创建一个缓冲区
	@Test
	public void test1() {
		String str = "abcde";
		
		//1.分配一个指定大小的缓冲区
		ByteBuffer buf = ByteBuffer.allocate(1024);
		System.out.println("---------------allocate()-----------------");
		System.out.println("position:"+buf.position());
		System.out.println("limit:"+buf.limit());
		System.out.println("capacity:"+buf.capacity());
		
		//2.利用put()存入数据到缓冲区中
		buf.put(str.getBytes());
		System.out.println("---------------put()-----------------");
		System.out.println("position:"+buf.position());
		System.out.println("limit:"+buf.limit());
		System.out.println("capacity:"+buf.capacity());
		
		//3.切换读取数据模式,利用flip()
		buf.flip();
		System.out.println("---------------flip()-----------------");
		System.out.println("position:"+buf.position());
		System.out.println("limit:"+buf.limit());
		System.out.println("capacity:"+buf.capacity());
	}
}

在这里插入图片描述

4.利用get() 读取缓冲区中的数据
package com.nio.test;

import java.nio.Buffer;
import java.nio.ByteBuffer;

import org.junit.Test;

/**
 * 一、缓冲区(Buffer):在JAVA的nio中 负责数据的存取。缓存区就是数组。用于存储不同数据类型的数据。
 * 
 * 根据数据类型不同(boolean除外),提供了相应类型的缓冲区:
 * ByteBuffer
 * CharBuffer
 * ShortBuffer
 * IntBuffer
 * LongBuffer
 * FloatBuffer
 * DoubleBuffer
 * 
 * 上述缓冲区的管理方式几乎一致,通过allocate()获取缓冲区
 * 
 * 二、缓冲区存取数据的两个核心方法
 * put() : 存入数据到缓冲区中
 * get() : 获取缓冲区中的数据
 * 
 * 三、缓冲区中的四个核心属性
 * capacity: 容量,表示缓冲区中最大存储数据的容量。一旦声明不能改变。
 * limit: 界限,表示缓冲区中可以操作数据的大小。(limit后数据不能进行读写)
 * position: 位置,表示缓冲区中正在操作数据的位置
 * position <= limit <= capacity
 * 
 */
public class TestBuffer {

	//创建一个缓冲区
	@Test
	public void test1() {
		String str = "abcde";
		
		//1.分配一个指定大小的缓冲区
		ByteBuffer buf = ByteBuffer.allocate(1024);
		System.out.println("---------------allocate()-----------------");
		System.out.println("position:"+buf.position());
		System.out.println("limit:"+buf.limit());
		System.out.println("capacity:"+buf.capacity());
		
		//2.利用put()存入数据到缓冲区中
		buf.put(str.getBytes());
		System.out.println("---------------put()-----------------");
		System.out.println("position:"+buf.position());
		System.out.println("limit:"+buf.limit());
		System.out.println("capacity:"+buf.capacity());
		
		//3.切换读取数据模式,利用flip()
		buf.flip();
		System.out.println("---------------flip()-----------------");
		System.out.println("position:"+buf.position());
		System.out.println("limit:"+buf.limit());
		System.out.println("capacity:"+buf.capacity());
		
		//4.利用get() 读取缓冲区中的数据
		byte[] dst = new byte[buf.limit()];
		buf.get(dst);
		System.out.println("---------------get()-----------------");
		System.out.println("position:"+buf.position());
		System.out.println("limit:"+buf.limit());
		System.out.println("capacity:"+buf.capacity());
		System.out.println(new String(dst,0,dst.length));
	}
}

在这里插入图片描述

5.rewind(): 将位置回到读模式,可重复读数据
package com.nio.test;

import java.nio.Buffer;
import java.nio.ByteBuffer;

import org.junit.Test;

/**
 * 一、缓冲区(Buffer):在JAVA的nio中 负责数据的存取。缓存区就是数组。用于存储不同数据类型的数据。
 * 
 * 根据数据类型不同(boolean除外),提供了相应类型的缓冲区:
 * ByteBuffer
 * CharBuffer
 * ShortBuffer
 * IntBuffer
 * LongBuffer
 * FloatBuffer
 * DoubleBuffer
 * 
 * 上述缓冲区的管理方式几乎一致,通过allocate()获取缓冲区
 * 
 * 二、缓冲区存取数据的两个核心方法
 * put() : 存入数据到缓冲区中
 * get() : 获取缓冲区中的数据
 * 
 * 三、缓冲区中的四个核心属性
 * capacity: 容量,表示缓冲区中最大存储数据的容量。一旦声明不能改变。
 * limit: 界限,表示缓冲区中可以操作数据的大小。(limit后数据不能进行读写)
 * position: 位置,表示缓冲区中正在操作数据的位置
 * position <= limit <= capacity
 * 
 */
public class TestBuffer {

	//创建一个缓冲区
	@Test
	public void test1() {
		String str = "abcde";
		
		//1.分配一个指定大小的缓冲区
		ByteBuffer buf = ByteBuffer.allocate(1024);
		System.out.println("---------------allocate()-----------------");
		System.out.println("position:"+buf.position());
		System.out.println("limit:"+buf.limit());
		System.out.println("capacity:"+buf.capacity());
		
		//2.利用put()存入数据到缓冲区中
		buf.put(str.getBytes());
		System.out.println("---------------put()-----------------");
		System.out.println("position:"+buf.position());
		System.out.println("limit:"+buf.limit());
		System.out.println("capacity:"+buf.capacity());
		
		//3.切换读取数据模式,利用flip()
		buf.flip();
		System.out.println("---------------flip()-----------------");
		System.out.println("position:"+buf.position());
		System.out.println("limit:"+buf.limit());
		System.out.println("capacity:"+buf.capacity());
		
		//4.利用get() 读取缓冲区中的数据
		byte[] dst = new byte[buf.limit()];
		buf.get(dst);
		System.out.println("---------------get()-----------------");
		System.out.println("position:"+buf.position());
		System.out.println("limit:"+buf.limit());
		System.out.println("capacity:"+buf.capacity());
		System.out.println(new String(dst,0,dst.length));
		
		//5.rewind(): 将位置回到读模式,可重复读数据
		buf.rewind();
		System.out.println("---------------rewind()-----------------");
		System.out.println("position:"+buf.position());
		System.out.println("limit:"+buf.limit());
		System.out.println("capacity:"+buf.capacity());
	}
}

在这里插入图片描述

6.clear() : 清空缓冲区

但是缓冲区中的数据并没有清空,依然存在,但是出于"被遗忘"状态。

package com.nio.test;

import java.nio.Buffer;
import java.nio.ByteBuffer;

import org.junit.Test;

/**
 * 一、缓冲区(Buffer):在JAVA的nio中 负责数据的存取。缓存区就是数组。用于存储不同数据类型的数据。
 * 
 * 根据数据类型不同(boolean除外),提供了相应类型的缓冲区:
 * ByteBuffer
 * CharBuffer
 * ShortBuffer
 * IntBuffer
 * LongBuffer
 * FloatBuffer
 * DoubleBuffer
 * 
 * 上述缓冲区的管理方式几乎一致,通过allocate()获取缓冲区
 * 
 * 二、缓冲区存取数据的两个核心方法
 * put() : 存入数据到缓冲区中
 * get() : 获取缓冲区中的数据
 * 
 * 三、缓冲区中的四个核心属性
 * capacity: 容量,表示缓冲区中最大存储数据的容量。一旦声明不能改变。
 * limit: 界限,表示缓冲区中可以操作数据的大小。(limit后数据不能进行读写)
 * position: 位置,表示缓冲区中正在操作数据的位置
 * position <= limit <= capacity
 * 
 */
public class TestBuffer {

	//创建一个缓冲区
	@Test
	public void test1() {
		String str = "abcde";
		
		//1.分配一个指定大小的缓冲区
		ByteBuffer buf = ByteBuffer.allocate(1024);
		System.out.println("---------------allocate()-----------------");
		System.out.println("position:"+buf.position());
		System.out.println("limit:"+buf.limit());
		System.out.println("capacity:"+buf.capacity());
		
		//2.利用put()存入数据到缓冲区中
		buf.put(str.getBytes());
		System.out.println("---------------put()-----------------");
		System.out.println("position:"+buf.position());
		System.out.println("limit:"+buf.limit());
		System.out.println("capacity:"+buf.capacity());
		
		//3.切换读取数据模式,利用flip()
		buf.flip();
		System.out.println("---------------flip()-----------------");
		System.out.println("position:"+buf.position());
		System.out.println("limit:"+buf.limit());
		System.out.println("capacity:"+buf.capacity());
		
		//4.利用get() 读取缓冲区中的数据
		byte[] dst = new byte[buf.limit()];
		buf.get(dst);
		System.out.println("---------------get()-----------------");
		System.out.println("position:"+buf.position());
		System.out.println("limit:"+buf.limit());
		System.out.println("capacity:"+buf.capacity());
		System.out.println(new String(dst,0,dst.length));
		
		//5.rewind(): 将位置回到读模式,可重复读数据
		buf.rewind();
		System.out.println("---------------rewind()-----------------");
		System.out.println("position:"+buf.position());
		System.out.println("limit:"+buf.limit());
		System.out.println("capacity:"+buf.capacity());
		
		//6.clear() : 清空缓冲区
		buf.clear();
		System.out.println("---------------clear()-----------------");
		System.out.println("position:"+buf.position());
		System.out.println("limit:"+buf.limit());
		System.out.println("capacity:"+buf.capacity());
	}
}

在这里插入图片描述

mark:标记,表示记录当前position的位置。可以通过reset() 恢复到mark的位置

0 <= mark <= position <= limit <= capacity

	@Test
	public void test2() {
		String str = "abcde";
		
		ByteBuffer buf = ByteBuffer.allocate(1024);
		
		buf.put(str.getBytes());
		
		buf.flip();
		
		byte[] dst = new byte[buf.limit()];
		
		buf.get(dst,0,2);
		
		System.out.println(new String(dst,0,2));
		
		System.out.println(buf.position());
		
		//mark()标记一下
		buf.mark();
		
		//buf.get(dst, offset, length)
		buf.get(dst, 2, 2);
		
		System.out.println(new String(dst,2,2));
		
		System.out.println(buf.position());
		
		//reset(): 恢复到mark的标记位置
		buf.reset();
		
		System.out.println(buf.position());
	}

在这里插入图片描述

7.hasRemaining()判断缓冲区中是否还有剩余数据
	@Test
	public void test2() {
		String str = "abcde";
		
		ByteBuffer buf = ByteBuffer.allocate(1024);
		
		buf.put(str.getBytes());
		
		buf.flip();
		
		byte[] dst = new byte[buf.limit()];
		
		buf.get(dst,0,2);
		
		System.out.println(new String(dst,0,2));
		
		System.out.println(buf.position());
		
		//mark()标记一下
		buf.mark();
		
		//buf.get(dst, offset, length)
		buf.get(dst, 2, 2);
		
		System.out.println(new String(dst,2,2));
		
		System.out.println(buf.position());
		
		//reset(): 恢复到mark的标记位置
		buf.reset();
		
		System.out.println(buf.position());
		
		
		System.out.println("--------------------");
		//判断缓冲区中是否还有剩余数据
		if(buf.hasRemaining()) {
			//获取缓冲区可以操作的数量
			System.out.println(buf.remaining());
		}
	}

在这里插入图片描述
在这里插入图片描述

直接缓冲区与非直接缓冲区

  • 非直接缓冲区:通过allocate()方法分配缓冲区,将缓冲区建立在JVM内存中。
  • 直接缓冲区:通过allocateDirect() 方法分配直接缓冲区,将缓冲区建立在物理内存中。可以提高效率。

非直接缓冲区

在这里插入图片描述

直接缓存区

文件通道(FileChannel)

NIO的非阻塞式网络通信

选择器

SocketChannel、ServerSocketChannel、DatagramChannel

管道(Pipe)

Java NIO2(Path、Paths与Files)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值