java nio 基础解析

访客 阅读:235 2021-03-31 21:15:38 评论:0

java nio 三大核心组件:

Buffers;

Channels;

Selectors;


Channels 和Buffers 的关系:

基本上,所有的 IO 在NIO 中都从一个Channel 开始。Channel 有点象流。 数据可以从Channel读到Buffer中,也可以从Buffer 写到Channel中。这里有个图示


JavaNio Channel通道实现类:

1、FileChannel  从文件中读取数据

2、DatagramChannel; UDP读取数据

3、SocketChannel;    TCP读取数据 

4、ServerSocketChannel;  结合SocketChannel 一起,进行TCP数据读取。

以上通过涵盖TCP 、UDP、网络IO和文件IO


JavaNio Buffer数据载体实现类:

1、ByteBuffer

2、CharBuffer

3、FloatBuffer

4、IntBuffer

5、LongBuffer

6、ShortBuffer

这些数据类型基本覆盖通过Java io发送的基础数据类型:byte、char、float、int、long、short.

java nio 拓展一个内存文件映射 MapperByteBuffer


Selector:

selector允许单线程处理多个Channel 通道,比如你创建的一个应用打开多个通道,但每个连接通道网络流量都很低时,select 使用就会很方便。

这是在一个单线程中使用一个Selector处理3个Channel的图示


要使用Selector,得向Selector注册Channel,然后调用它的select()方法。这个方法会一直阻塞到某个注册的通道有事件就绪。一旦这个方法返回,线程就可以处理这些事件,事件的例子有如新连接进来,数据接收等。


功能代码一:将数据读取到缓存中,并且输出内存缓存的内容。

package com.nio.one; 
 
import java.io.File; 
import java.io.FileInputStream; 
import java.io.FileNotFoundException; 
import java.io.IOException; 
import java.nio.ByteBuffer; 
import java.nio.channels.FileChannel; 
 
public class FileNioRead { 
	private String path; 
 
	public FileNioRead(String path) { 
		this.path = path; 
	} 
 
	public String getPath() { 
		return path; 
	} 
 
	public void setPath(String path) { 
		this.path = path; 
	} 
	 
	//读取指定路径文件信息,到内存中,通过nio 
	public String getContent() throws IOException{ 
		String content = ""; 
		try { 
			//创建输入流通道FileChannel 
			FileInputStream in = new FileInputStream(new File(this.path)); 
			FileChannel inChannel = in.getChannel(); 
			//创建承接数据载体Buffer 
			ByteBuffer buffer = ByteBuffer.allocate(1024); 
			 
			//判断数据是否读取完毕 
			while(true){			 
				//数据开始读取 
				int num = inChannel.read(buffer); 
				 //判断数据是否读取完毕   
	            if (num == -1) {   
	                break;   
	            } 	             
			} 
			//打印Buffer 对象信息 
			System.out.println("buffer.toString 方法:"+buffer.toString()); 
			//暂时获取已经写入缓存的数据信息(文件内容)			 
			content = new String(buffer.array()); 
			 
		 
			 
		} catch (FileNotFoundException e) { 
			// TODO Auto-generated catch block 
			e.printStackTrace(); 
			 
		} 
		 
		return content; 
	} 
 
	public static void main(String[] args) { 
		// TODO Auto-generated method stub 
		FileNioRead read = new FileNioRead("D:\\demo.txt"); 
		try { 
			String context = read.getContent(); 
			System.out.println("文件内容:"+context); 
		} catch (IOException e) { 
			// TODO Auto-generated catch block 
			e.printStackTrace(); 
		} 
	} 
 
} 


功能二代码:实现两文件直接内容的copy

package com.nio.one; 
 
import java.io.File; 
import java.io.FileInputStream; 
import java.io.FileOutputStream; 
import java.nio.ByteBuffer; 
import java.nio.channels.FileChannel; 
 
public class FileCopyUtil { 
	private String to; 
	private String from; 
 
	public FileCopyUtil(String to, String from) { 
		this.to = to; 
		this.from = from; 
	} 
 
	public String getTo() { 
		return to; 
	} 
 
	public void setTo(String to) { 
		this.to = to; 
	} 
 
	public String getFrom() { 
		return from; 
	} 
 
	public boolean copy() throws Exception { 
		boolean target = false; 
		 
		FileInputStream in = new FileInputStream(new File(this.to));		 
		FileOutputStream out = new FileOutputStream(new File(this.from)); 
		//获取文件读取通道 
		FileChannel inChannel = in.getChannel(); 
		//获取文件写入通道 
		FileChannel outChannel = out.getChannel(); 
		 
        //定义缓存区大小 
		ByteBuffer buffer = ByteBuffer.allocate(1024); 
 
		while (true) { 
			// 清空缓存空间 
			buffer.clear(); 
			//读取数据到缓存区 
			int num = inChannel.read(buffer); 
			if (num == -1) { 
				break; 
			} 
			//将buffer 指针指向头部 
			buffer.flip(); 
			//将缓存数据写入通道 
			outChannel.write(buffer); 
		} 
		target = true; 
		return target; 
	} 
 
	public void setFrom(String from) { 
		this.from = from; 
	} 
 
	public static void main(String[] args) throws Exception { 
		// TODO Auto-generated method stub 
		FileCopyUtil util = new FileCopyUtil("D:\\demo.txt", "D:\\one.txt"); 
		boolean target = util.copy(); 
		System.out.println("file copy is successful:"+target); 
 
	} 
 
} 

功能代码三:java udp 服务端和客户端实现。

服务端代码:

package com.nio.channel; 
 
import java.io.IOException; 
import java.net.InetSocketAddress; 
import java.nio.ByteBuffer; 
import java.nio.channels.DatagramChannel; 
import java.nio.charset.Charset; 
 
public class UDPServer { 
 
	public static void main(String[] args) { 
		try { 
			// 打开数据包通道 
			DatagramChannel channel = DatagramChannel.open(); 
			// 获取与此通道关联的数据报套接字 
			channel.socket().bind(new InetSocketAddress(8888)); 
			// 分配一个新的字节缓冲区。 
			ByteBuffer buffer = ByteBuffer.allocate(1024); 
			// 判断数据包通道中是否存在数据 
			while (channel.receive(buffer) == null) { 
				try { 
					Thread.sleep(2000); 
				} catch (InterruptedException e) { 
					e.printStackTrace(); 
				} 
			} 
			//反转此缓冲区(写模式---读模式) 
			buffer.flip(); 
			//接受字符 
			String recStr =Charset.forName("UTF-8").newDecoder().decode(buffer).toString(); 
			System.out.println(recStr); 
			channel.close(); 
		} catch (IOException e) { 
			// TODO Auto-generated catch block 
			e.printStackTrace(); 
		} 
 
	} 
 
} 

客户端代码:

package com.nio.channel; 
 
import java.io.IOException; 
import java.net.InetSocketAddress; 
import java.nio.ByteBuffer; 
import java.nio.channels.DatagramChannel; 
 
public class UDPClient { 
 
	public static void main(String[] args) { 
		// TODO Auto-generated method stub 
		try {// 打开数据包通道 
			DatagramChannel channel = DatagramChannel.open(); 
			// 将 byte 数组写入缓冲区中 
			ByteBuffer buffer = ByteBuffer.wrap("左青龙右白虎,南朱雀北玄武".getBytes("UTF-8")); 
			// 绑定与服务UDP通道关联的数据报套接字 
			channel.send(buffer, new InetSocketAddress("127.0.0.1", 8888)); 
			channel.close(); 
		} catch (IOException e) { 
			e.printStackTrace(); 
		} 
 
	} 
 
} 

java nio 功能的基础讲解就到这里。下一篇,我们将重点分析Buffer 接口的用法。




声明

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

发表评论
搜索
排行榜
KIKK导航

KIKK导航

关注我们