java_nio基础篇之Channel、Selector、Path、Paths、Pipe、Files


参考

http://tutorials.jenkov.com/java-nio/pipe.html


先来看些nio基础的类库关系图 用pd大致画了下





相关的图片




上面是一些理论的关系图 下面是一些测试代码  相关的代码 都加了必要的注释

文件通道  FileChannel

package com.undergrowth;

import java.io.IOException;
import java.io.RandomAccessFile;
import java.net.URISyntaxException;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousFileChannel;
import java.nio.channels.CompletionHandler;
import java.nio.channels.FileChannel;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;


/**
 * 文件通道测试类
 * 文件通道只能使用阻塞模式
 * A FileChannel cannot be set into non-blocking mode. It always runs in blocking mode
 * @author u1
 *
 */
public class BasicFileChannel {

	RandomAccessFile randomAccessFile;
	FileChannel channel;
	ByteBuffer buffer;
	
	@Before
	public void before() throws IOException{
		randomAccessFile=new RandomAccessFile(ClassLoader.getSystemResource("selector.txt").getFile(), "rw");
		channel=randomAccessFile.getChannel();
		//强制刷新
		channel.force(true);
		buffer=ByteBuffer.allocate(1024);
	}
	
	@After
	public void after() throws IOException{
		randomAccessFile.close();
		channel.close();
	}
	
	/**
	 * //1、读取数据Buffer
		//2、转换模式
		//3、读取Buffer
		//4、清除Buffers
	 * @throws IOException 
	 */
	@Test
	public void readTest() throws IOException{
		System.out.println(read());
	}

	private String read() throws IOException {
		StringBuilder builder=new StringBuilder();
		int readByte=channel.read(buffer);
		while(readByte!=-1){
			//1、读取数据Buffer
			//2、转换模式
			buffer.flip();
			//3、读取Buffer
			byte[] datas=new byte[buffer.limit()];
			buffer.get(datas);
			//System.out.println(new String(datas));
			builder.append(new String(datas));
			//4、清除Buffer
			buffer.clear();
		 readByte=channel.read(buffer);
		}
		 return builder.toString();
	}
	
	/**
	 * 将读出的文件内容回写到文件中  
	 * 从文件的开始地方写入
	 * @throws IOException
	 */
	@Test
	public void writeTest() throws IOException{
		//获取原有字符串
		String originString=read();
		originString+=System.currentTimeMillis();
		//写入到buffer
		buffer.put(originString.getBytes());
		//转换模式
		buffer.flip();
		//将buffer中的数据写入到文件中
		channel.position(0);
		System.out.println("size:"+channel.size()+"\t"+"position:"+channel.position());
		while(buffer.hasRemaining()) channel.write(buffer);
		
	}
	
	@Test
	public void writeAsyncTest() throws IOException, URISyntaxException{
		//获取原有字符串
	String originString=read();
	originString+=System.currentTimeMillis();
	//写入到buffer
	buffer.put(originString.getBytes());
	//转换模式
	buffer.flip();
	Path file=Paths.get(ClassLoader.getSystemResource("selector1.txt").toURI());
	AsynchronousFileChannel fileChannel=AsynchronousFileChannel.open(file, StandardOpenOption.WRITE);
	fileChannel.force(true);
	fileChannel.write(buffer, 0, buffer, new CompletionHandler<Integer, ByteBuffer>() {

		@Override
		public void completed(Integer result, ByteBuffer attachment) {
			// TODO Auto-generated method stub
			System.out.println("已经写了"+result);
		}

		@Override
		public void failed(Throwable exc, ByteBuffer attachment) {
			// TODO Auto-generated method stub
			System.out.println("写失败");
			exc.printStackTrace();
		}
	});
	System.out.println(fileChannel.isOpen());
	fileChannel.close();
	}
}



多路复用器  Selector

服务端

package com.undergrowth;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.util.Iterator;
import java.util.Set;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

/**
 * 测试多路复用器 Selector
 * @author u1
 *
 */
public class BasicSelector {
	
	//多路复用器  检测7777和8888端口
	private Selector selector;
	private ServerSocketChannel channel7777,channel8888;
	
	@Before
	public void before() throws IOException{
		selector=Selector.open();
		//打开7777端口服务通道
		channel7777=ServerSocketChannel.open();
		//绑定7777端口的服务监听
		channel7777.socket().bind(new InetSocketAddress(7777));
		//配置为非阻塞模式
		channel7777.configureBlocking(false);
		//将通道注册到多路复用器上
		channel7777.register(selector,  SelectionKey.OP_ACCEPT);
		//打开8888端口服务通道
		channel8888=ServerSocketChannel.open();
		//绑定8888端口的服务监听
		channel8888.socket().bind(new InetSocketAddress(9999));
		//配置为非阻塞模式
		channel8888.configureBlocking(false);
		//关注读操作
		channel8888.register(selector, SelectionKey.OP_ACCEPT);
	}
	
	/**
	 * 关闭资源
	 * @throws IOException
	 */
	@After
	public void after() throws IOException{
		selector.close();
		channel7777.close();
		channel8888.close();
	}
	
	@Test
	public void select() throws IOException{
		//控制循环
		BufferedReader reader=new BufferedReader(new InputStreamReader(System.in));
		while(true){
			System.out.println("是否还要进行");
			String isGoString=reader.readLine();
			if("N".equalsIgnoreCase(isGoString)) break;
			System.out.println("等待事件源发生");
			//等待注册的事件源发生
			int readyChannel=selector.select();
			if(readyChannel==0) continue;
			System.out.println("有"+readyChannel+"个准备好了");
			//获取准备好的通道
			Set<SelectionKey> selectionKeys=selector.selectedKeys();
			Iterator<SelectionKey> selectKeyIterator=selectionKeys.iterator();
			while (selectKeyIterator.hasNext()) {
				SelectionKey selectionKey = (SelectionKey) selectKeyIterator
						.next();
				//遍历注册中准备好的事件源
				interestSet(selectionKey.interestOps());
				if(selectionKey.isAcceptable()){
					//当客户端进行连接时  获取socket  会写信息
					ServerSocketChannel serverSocketChannel=(ServerSocketChannel) selectionKey.channel();
					System.out.println(serverSocketChannel.socket().getLocalPort()+"端口\t"+"感兴趣的操作:"+serverSocketChannel.validOps());
					Socket socket=serverSocketChannel.socket().accept();
					socket.getOutputStream().write("从selector中返回给客户端".getBytes());
					socket.getOutputStream().flush();
					socket.close();
				}
				//移除已经处理的事件源
				selectKeyIterator.remove();
			}
		}
		
		
	}

	/**
	 * 遍历注册中准备好的事件源
	 * @param interestOps
	 */
	private void interestSet(int interestSet) {
		// TODO Auto-generated method stub
		if((interestSet&SelectionKey.OP_ACCEPT)!=0) System.out.println("注册的可接受");
		if((interestSet&SelectionKey.OP_CONNECT)!=0) System.out.println("注册的可连接");
		if((interestSet&SelectionKey.OP_READ)!=0) System.out.println("注册的可读");
		if((interestSet&SelectionKey.OP_WRITE)!=0) System.out.println("注册的可写");
	}
	
	
}


客户端

package com.undergrowth;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.InetSocketAddress;
import java.net.Socket;


/**
 * 连接服务ServerSocket
 * @author u1
 *
 */
public class BasicSocketChannel {

	/**
	 * @param args
	 * @throws IOException 
	 */
	public static void main(String[] args) throws IOException {
		// TODO Auto-generated method stub
		
		//用于客户端的Socket连接 测试
		Socket socket=new Socket();
		socket.connect(new InetSocketAddress(7777));
		BufferedReader reader=new BufferedReader(new InputStreamReader(socket.getInputStream())); 
		System.out.println("读取的字符串为:"+reader.readLine());
		
	}

}


路径   Path与Paths

package com.undergrowth;

import java.nio.file.Path;
import java.nio.file.Paths;

import org.junit.Test;

/**
 * A Java Path instance represents a path in the file system. A path can point
 * to either a file or a directory. A path can be absolute or relative. An
 * absolute path contains the full path from the root of the file system down to
 * the file or directory it points to. A relative path contains the path to the
 * file or directory relative to some other path.
 * 
 * @author u1
 * 
 */
public class BasicPath {

	/**
	 * 测试绝对路径
	 */
	@Test
	public void testAbsolute() {
		Path path=Paths.get("E:\\book", "JAVA_API_1.7中文.chm");
		System.out.println(path.toString());
	}

	/**
	 * 测试相对路径
	 * .---->当前路径
	 * ..---->父路径
	 */
	@Test
	public void testRelative(){
		Path path=Paths.get(".");
		System.out.println(path.toAbsolutePath());
		path=Paths.get("..");
		System.out.println(path.toAbsolutePath());
	}
	
	/**
	 * 格式化Path路径 
	 * 去除.和..
	 */
	@Test
	public void testNormalize(){
		Path path=Paths.get("E:\\book\\weblogic\\.\\51CTO下载-Oracle WebLogic Server开发权威指南.part1.rar");
		System.out.println(path.toAbsolutePath());
		System.out.println(path.normalize().toAbsolutePath());
		path=Paths.get("E:\\book\\..\\");
		System.out.println(path.toAbsolutePath());
		System.out.println(path.normalize().toAbsolutePath());
	}
	
}



管道  Pipe

package com.undergrowth;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.Pipe;

import org.junit.Before;
import org.junit.Test;

/**
 * 管道操作
 * 
 * A Java NIO Pipe is a one-way data connection between two threads. A Pipe has
 * a source channel and a sink channel. You write data to the sink channel. This
 * data can then be read from the source channel
 * 
 * @author u1
 * 
 */
public class BasicPipe {

	Pipe pipe;
	Pipe.SinkChannel writePipe;
	Pipe.SourceChannel readPipe;
	ByteBuffer buffer;
	
	@Before
	public void before() throws IOException{
		pipe=Pipe.open();
		writePipe=pipe.sink();
		readPipe=pipe.source();
		buffer=ByteBuffer.allocate(1024);
	}
	
	@Test
	public void testPipe() throws IOException{
		String string="通过管道进行传输数据";
		buffer.put(string.getBytes());
		buffer.flip();
		//将数据写入接受的通道中
		while(buffer.hasRemaining()) writePipe.write(buffer);
		//将数据从读的通道中读出
		ByteBuffer byteBuffer=ByteBuffer.allocate(1024);
		StringBuilder builder=new StringBuilder();
		int readByte=readPipe.read(byteBuffer);
		byteBuffer.flip();
		byte[] dst=new byte[byteBuffer.limit()];
		byteBuffer.get(dst);
		builder.append(new String(dst));
		byteBuffer.clear();
		System.out.println("从读的通道中读出的数据为:"+builder.toString());
	}
}



文件  Files

package com.undergrowth;

import static org.junit.Assert.*;

import java.io.IOException;
import java.nio.file.FileVisitResult;
import java.nio.file.FileVisitor;
import java.nio.file.Files;
import java.nio.file.LinkOption;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.StandardCopyOption;
import java.nio.file.attribute.BasicFileAttributes;

import org.junit.Test;

/**
 * The Java NIO Files class (java.nio.file.Files) provides several methods for
 * manipulating files in the file system.
 * 文件操作类
 *    新建两个文件夹 再将文件复制到两文件夹中 然后进行遍历文件树 遍历完成后 删除文件夹及文件
 * @author u1
 * 
 */
public class BasicFiles {

	@Test
	public void test() throws IOException {
		//获取路径
		Path path=Paths.get(".\\test");
		//分别创建两个文件夹 在test里面 分别为test1 和  test2
		createDir(path);
		//复制文件
		copyFiles(path);
		//遍历文件
		path=Paths.get(".\\test");
		walkFile(path);
	}

	/**
	 * 遍历文件目录
	 * @param path
	 * @throws IOException 
	 */
	private void walkFile(Path path) throws IOException {
		// TODO Auto-generated method stub
		Files.walkFileTree(path, new SimpleFileVisitor<Path>(){

			@Override
			public FileVisitResult visitFile(Path file,
					BasicFileAttributes attrs) throws IOException {
				// TODO Auto-generated method stub
				//删除文件
				System.out.println("删除"+file.toFile().getAbsolutePath());
				Files.delete(file);
				return FileVisitResult.CONTINUE;
			}

			@Override
			public FileVisitResult postVisitDirectory(Path dir, IOException exc)
					throws IOException {
				// TODO Auto-generated method stub
				//遍历完目录后删除
				System.out.println("遍历完目录后删除"+dir.toAbsolutePath());
				Files.delete(dir);
				return FileVisitResult.CONTINUE;
			}
			
		});
	}

	/**
	 * 复制文件
	 * @param path
	 * @throws IOException 
	 */
	private void copyFiles(Path path) throws IOException {
		// TODO Auto-generated method stub
		Path pathSource =Paths.get("..\\git.txt");
		path=Paths.get(".\\test\\test1\\git.txt");
		//替换已经存在的文件
		Files.copy(pathSource, path,StandardCopyOption.REPLACE_EXISTING);
		path=Paths.get(".\\test\\test2\\git.txt");
		Files.copy(pathSource, path,StandardCopyOption.REPLACE_EXISTING);
	}

	/**
	 * 创建文件夹
	 * @param path
	 * @throws IOException
	 */
	private void createDir(Path path) throws IOException {
		// TODO Auto-generated method stub
		if(!Files.exists(path, new LinkOption[]{LinkOption.NOFOLLOW_LINKS}))
			Files.createDirectories(path);
		path=Paths.get(path.toString(), "test1");
		if(!Files.exists(path, new LinkOption[]{LinkOption.NOFOLLOW_LINKS}))
			Files.createDirectories(path);
		path=Paths.get(path.toString(), "..\\test2");
		if(!Files.exists(path, new LinkOption[]{LinkOption.NOFOLLOW_LINKS}))
			Files.createDirectories(path);
	}

	
}











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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值