java nio 异步操作 (一)

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

java nio 异步操作 (一)


java nio 异步操作 (一)




相关的图片

java nio 异步操作 (一)


java nio 异步操作 (一)



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

文件通道  FileChannel

package test;

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;


/**
 * 文件通道测试类
 * FileChannel文件通道只能使用阻塞模式
 * AsynchronousFileChannel 异步 可以使用异步模式
 * 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;
	AsynchronousFileChannel fileChannel;
	
	@Before
	public void before() throws IOException{
		randomAccessFile=new RandomAccessFile(ClassLoader.getSystemResource("selector.txt").getFile(), "rw");
		channel=randomAccessFile.getChannel();
		//强制刷新
		channel.force(true);
		buffer=ByteBuffer.allocate(102400);
		String aaa=buffer.toString();
		System.out.println(aaa);
	}
	
	@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);
		}
		 String aa=builder.toString();
		 return aa;
	}
	
	/**
	 * 将读出的文件内容回写到文件中  
	 * 从文件的开始地方写入
	 * @throws IOException
	 */
	@Test
	public void writeTest() {
		try {
		
		//获取原有字符串
		String originString=read();
		//写入到buffer
		buffer.put(originString.getBytes());
		//转换模式
		buffer.flip();
		//将buffer中的数据写入到文件中
		channel.position(0);
		System.out.println("size:"+channel.size()+"\t"+"position:"+channel.position());
		@SuppressWarnings("resource")
		RandomAccessFile randomAccessFile2=new RandomAccessFile("/home/lhy/data/aaaa.txt", "rw");
	
		FileChannel channel2=randomAccessFile2.getChannel();
		while(buffer.hasRemaining())
		{
			channel2.write(buffer);
			System.out.println("0000000000000000");
		}
		
		} catch (Exception e) {
			e.printStackTrace();
		}
		System.out.println("11111111111111111111111");
		
	}
	
	//@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());
	Path file=Paths.get("/home/lhy/data/aaaa.txt");
	fileChannel=AsynchronousFileChannel.open(file, StandardOpenOption.WRITE);
	fileChannel.force(true);
	//fileChannel.write(buffer, 10);
	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);
			close();
		}

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




多路复用器  Selector

服务端

  1. package com.undergrowth;  
  2.   
  3. import java.io.BufferedReader;  
  4. import java.io.IOException;  
  5. import java.io.InputStreamReader;  
  6. import java.net.InetSocketAddress;  
  7. import java.net.Socket;  
  8. import java.nio.channels.SelectionKey;  
  9. import java.nio.channels.Selector;  
  10. import java.nio.channels.ServerSocketChannel;  
  11. import java.util.Iterator;  
  12. import java.util.Set;  
  13.   
  14. import org.junit.After;  
  15. import org.junit.Before;  
  16. import org.junit.Test;  
  17.   
  18. /** 
  19.  * 测试多路复用器 Selector 
  20.  * @author u1 
  21.  * 
  22.  */  
  23. public class BasicSelector {  
  24.       
  25.     //多路复用器  检测7777和8888端口  
  26.     private Selector selector;  
  27.     private ServerSocketChannel channel7777,channel8888;  
  28.       
  29.     @Before  
  30.     public void before() throws IOException{  
  31.         selector=Selector.open();  
  32.         //打开7777端口服务通道  
  33.         channel7777=ServerSocketChannel.open();  
  34.         //绑定7777端口的服务监听  
  35.         channel7777.socket().bind(new InetSocketAddress(7777));  
  36.         //配置为非阻塞模式  
  37.         channel7777.configureBlocking(false);  
  38.         //将通道注册到多路复用器上  
  39.         channel7777.register(selector,  SelectionKey.OP_ACCEPT);  
  40.         //打开8888端口服务通道  
  41.         channel8888=ServerSocketChannel.open();  
  42.         //绑定8888端口的服务监听  
  43.         channel8888.socket().bind(new InetSocketAddress(9999));  
  44.         //配置为非阻塞模式  
  45.         channel8888.configureBlocking(false);  
  46.         //关注读操作  
  47.         channel8888.register(selector, SelectionKey.OP_ACCEPT);  
  48.     }  
  49.       
  50.     /** 
  51.      * 关闭资源 
  52.      * @throws IOException 
  53.      */  
  54.     @After  
  55.     public void after() throws IOException{  
  56.         selector.close();  
  57.         channel7777.close();  
  58.         channel8888.close();  
  59.     }  
  60.       
  61.     @Test  
  62.     public void select() throws IOException{  
  63.         //控制循环  
  64.         BufferedReader reader=new BufferedReader(new InputStreamReader(System.in));  
  65.         while(true){  
  66.             System.out.println("是否还要进行");  
  67.             String isGoString=reader.readLine();  
  68.             if("N".equalsIgnoreCase(isGoString)) break;  
  69.             System.out.println("等待事件源发生");  
  70.             //等待注册的事件源发生  
  71.             int readyChannel=selector.select();  
  72.             if(readyChannel==0continue;  
  73.             System.out.println("有"+readyChannel+"个准备好了");  
  74.             //获取准备好的通道  
  75.             Set<SelectionKey> selectionKeys=selector.selectedKeys();  
  76.             Iterator<SelectionKey> selectKeyIterator=selectionKeys.iterator();  
  77.             while (selectKeyIterator.hasNext()) {  
  78.                 SelectionKey selectionKey = (SelectionKey) selectKeyIterator  
  79.                         .next();  
  80.                 //遍历注册中准备好的事件源  
  81.                 interestSet(selectionKey.interestOps());  
  82.                 if(selectionKey.isAcceptable()){  
  83.                     //当客户端进行连接时  获取socket  会写信息  
  84.                     ServerSocketChannel serverSocketChannel=(ServerSocketChannel) selectionKey.channel();  
  85.                     System.out.println(serverSocketChannel.socket().getLocalPort()+"端口\t"+"感兴趣的操作:"+serverSocketChannel.validOps());  
  86.                     Socket socket=serverSocketChannel.socket().accept();  
  87.                     socket.getOutputStream().write("从selector中返回给客户端".getBytes());  
  88.                     socket.getOutputStream().flush();  
  89.                     socket.close();  
  90.                 }  
  91.                 //移除已经处理的事件源  
  92.                 selectKeyIterator.remove();  
  93.             }  
  94.         }  
  95.           
  96.           
  97.     }  
  98.   
  99.     /** 
  100.      * 遍历注册中准备好的事件源 
  101.      * @param interestOps 
  102.      */  
  103.     private void interestSet(int interestSet) {  
  104.         // TODO Auto-generated method stub  
  105.         if((interestSet&SelectionKey.OP_ACCEPT)!=0) System.out.println("注册的可接受");  
  106.         if((interestSet&SelectionKey.OP_CONNECT)!=0) System.out.println("注册的可连接");  
  107.         if((interestSet&SelectionKey.OP_READ)!=0) System.out.println("注册的可读");  
  108.         if((interestSet&SelectionKey.OP_WRITE)!=0) System.out.println("注册的可写");  
  109.     }  
  110.       
  111.       
  112. }  


客户端

  1. package com.undergrowth;  
  2.   
  3. import java.io.BufferedReader;  
  4. import java.io.IOException;  
  5. import java.io.InputStreamReader;  
  6. import java.net.InetSocketAddress;  
  7. import java.net.Socket;  
  8.   
  9.   
  10. /** 
  11.  * 连接服务ServerSocket 
  12.  * @author u1 
  13.  * 
  14.  */  
  15. public class BasicSocketChannel {  
  16.   
  17.     /** 
  18.      * @param args 
  19.      * @throws IOException  
  20.      */  
  21.     public static void main(String[] args) throws IOException {  
  22.         // TODO Auto-generated method stub  
  23.           
  24.         //用于客户端的Socket连接 测试  
  25.         Socket socket=new Socket();  
  26.         socket.connect(new InetSocketAddress(7777));  
  27.         BufferedReader reader=new BufferedReader(new InputStreamReader(socket.getInputStream()));   
  28.         System.out.println("读取的字符串为:"+reader.readLine());  
  29.           
  30.     }  
  31.   
  32. }  


路径   Path与Paths

  1. package com.undergrowth;  
  2.   
  3. import java.nio.file.Path;  
  4. import java.nio.file.Paths;  
  5.   
  6. import org.junit.Test;  
  7.   
  8. /** 
  9.  * A Java Path instance represents a path in the file system. A path can point 
  10.  * to either a file or a directory. A path can be absolute or relative. An 
  11.  * absolute path contains the full path from the root of the file system down to 
  12.  * the file or directory it points to. A relative path contains the path to the 
  13.  * file or directory relative to some other path. 
  14.  *  
  15.  * @author u1 
  16.  *  
  17.  */  
  18. public class BasicPath {  
  19.   
  20.     /** 
  21.      * 测试绝对路径 
  22.      */  
  23.     @Test  
  24.     public void testAbsolute() {  
  25.         Path path=Paths.get("E:\\book""JAVA_API_1.7中文.chm");  
  26.         System.out.println(path.toString());  
  27.     }  
  28.   
  29.     /** 
  30.      * 测试相对路径 
  31.      * .---->当前路径 
  32.      * ..---->父路径 
  33.      */  
  34.     @Test  
  35.     public void testRelative(){  
  36.         Path path=Paths.get(".");  
  37.         System.out.println(path.toAbsolutePath());  
  38.         path=Paths.get("..");  
  39.         System.out.println(path.toAbsolutePath());  
  40.     }  
  41.       
  42.     /** 
  43.      * 格式化Path路径  
  44.      * 去除.和.. 
  45.      */  
  46.     @Test  
  47.     public void testNormalize(){  
  48.         Path path=Paths.get("E:\\book\\weblogic\\.\\51CTO下载-Oracle WebLogic Server开发权威指南.part1.rar");  
  49.         System.out.println(path.toAbsolutePath());  
  50.         System.out.println(path.normalize().toAbsolutePath());  
  51.         path=Paths.get("E:\\book\\..\\");  
  52.         System.out.println(path.toAbsolutePath());  
  53.         System.out.println(path.normalize().toAbsolutePath());  
  54.     }  
  55.       
  56. }  



管道  Pipe

  1. package com.undergrowth;  
  2.   
  3. import java.io.IOException;  
  4. import java.nio.ByteBuffer;  
  5. import java.nio.channels.Pipe;  
  6.   
  7. import org.junit.Before;  
  8. import org.junit.Test;  
  9.   
  10. /** 
  11.  * 管道操作 
  12.  *  
  13.  * A Java NIO Pipe is a one-way data connection between two threads. A Pipe has 
  14.  * a source channel and a sink channel. You write data to the sink channel. This 
  15.  * data can then be read from the source channel 
  16.  *  
  17.  * @author u1 
  18.  *  
  19.  */  
  20. public class BasicPipe {  
  21.   
  22.     Pipe pipe;  
  23.     Pipe.SinkChannel writePipe;  
  24.     Pipe.SourceChannel readPipe;  
  25.     ByteBuffer buffer;  
  26.       
  27.     @Before  
  28.     public void before() throws IOException{  
  29.         pipe=Pipe.open();  
  30.         writePipe=pipe.sink();  
  31.         readPipe=pipe.source();  
  32.         buffer=ByteBuffer.allocate(1024);  
  33.     }  
  34.       
  35.     @Test  
  36.     public void testPipe() throws IOException{  
  37.         String string="通过管道进行传输数据";  
  38.         buffer.put(string.getBytes());  
  39.         buffer.flip();  
  40.         //将数据写入接受的通道中  
  41.         while(buffer.hasRemaining()) writePipe.write(buffer);  
  42.         //将数据从读的通道中读出  
  43.         ByteBuffer byteBuffer=ByteBuffer.allocate(1024);  
  44.         StringBuilder builder=new StringBuilder();  
  45.         int readByte=readPipe.read(byteBuffer);  
  46.         byteBuffer.flip();  
  47.         byte[] dst=new byte[byteBuffer.limit()];  
  48.         byteBuffer.get(dst);  
  49.         builder.append(new String(dst));  
  50.         byteBuffer.clear();  
  51.         System.out.println("从读的通道中读出的数据为:"+builder.toString());  
  52.     }  
  53. }  



文件  Files

  1. package com.undergrowth;  
  2.   
  3. import static org.junit.Assert.*;  
  4.   
  5. import java.io.IOException;  
  6. import java.nio.file.FileVisitResult;  
  7. import java.nio.file.FileVisitor;  
  8. import java.nio.file.Files;  
  9. import java.nio.file.LinkOption;  
  10. import java.nio.file.Path;  
  11. import java.nio.file.Paths;  
  12. import java.nio.file.SimpleFileVisitor;  
  13. import java.nio.file.StandardCopyOption;  
  14. import java.nio.file.attribute.BasicFileAttributes;  
  15.   
  16. import org.junit.Test;  
  17.   
  18. /** 
  19.  * The Java NIO Files class (java.nio.file.Files) provides several methods for 
  20.  * manipulating files in the file system. 
  21.  * 文件操作类 
  22.  *    新建两个文件夹 再将文件复制到两文件夹中 然后进行遍历文件树 遍历完成后 删除文件夹及文件 
  23.  * @author u1 
  24.  *  
  25.  */  
  26. public class BasicFiles {  
  27.   
  28.     @Test  
  29.     public void test() throws IOException {  
  30.         //获取路径  
  31.         Path path=Paths.get(".\\test");  
  32.         //分别创建两个文件夹 在test里面 分别为test1 和  test2  
  33.         createDir(path);  
  34.         //复制文件  
  35.         copyFiles(path);  
  36.         //遍历文件  
  37.         path=Paths.get(".\\test");  
  38.         walkFile(path);  
  39.     }  
  40.   
  41.     /** 
  42.      * 遍历文件目录 
  43.      * @param path 
  44.      * @throws IOException  
  45.      */  
  46.     private void walkFile(Path path) throws IOException {  
  47.         // TODO Auto-generated method stub  
  48.         Files.walkFileTree(path, new SimpleFileVisitor<Path>(){  
  49.   
  50.             @Override  
  51.             public FileVisitResult visitFile(Path file,  
  52.                     BasicFileAttributes attrs) throws IOException {  
  53.                 // TODO Auto-generated method stub  
  54.                 //删除文件  
  55.                 System.out.println("删除"+file.toFile().getAbsolutePath());  
  56.                 Files.delete(file);  
  57.                 return FileVisitResult.CONTINUE;  
  58.             }  
  59.   
  60.             @Override  
  61.             public FileVisitResult postVisitDirectory(Path dir, IOException exc)  
  62.                     throws IOException {  
  63.                 // TODO Auto-generated method stub  
  64.                 //遍历完目录后删除  
  65.                 System.out.println("遍历完目录后删除"+dir.toAbsolutePath());  
  66.                 Files.delete(dir);  
  67.                 return FileVisitResult.CONTINUE;  
  68.             }  
  69.               
  70.         });  
  71.     }  
  72.   
  73.     /** 
  74.      * 复制文件 
  75.      * @param path 
  76.      * @throws IOException  
  77.      */  
  78.     private void copyFiles(Path path) throws IOException {  
  79.         // TODO Auto-generated method stub  
  80.         Path pathSource =Paths.get("..\\git.txt");  
  81.         path=Paths.get(".\\test\\test1\\git.txt");  
  82.         //替换已经存在的文件  
  83.         Files.copy(pathSource, path,StandardCopyOption.REPLACE_EXISTING);  
  84.         path=Paths.get(".\\test\\test2\\git.txt");  
  85.         Files.copy(pathSource, path,StandardCopyOption.REPLACE_EXISTING);  
  86.     }  
  87.   
  88.     /** 
  89.      * 创建文件夹 
  90.      * @param path 
  91.      * @throws IOException 
  92.      */  
  93.     private void createDir(Path path) throws IOException {  
  94.         // TODO Auto-generated method stub  
  95.         if(!Files.exists(path, new LinkOption[]{LinkOption.NOFOLLOW_LINKS}))  
  96.             Files.createDirectories(path);  
  97.         path=Paths.get(path.toString(), "test1");  
  98.         if(!Files.exists(path, new LinkOption[]{LinkOption.NOFOLLOW_LINKS}))  
  99.             Files.createDirectories(path);  
  100.         path=Paths.get(path.toString(), "..\\test2");  
  101.         if(!Files.exists(path, new LinkOption[]{LinkOption.NOFOLLOW_LINKS}))  
  102.             Files.createDirectories(path);  
  103.     }  
  104.   
  105.       
  106. }  


上一篇:sql查询,如果有更新时间则按更新时间倒序,没有则按创建时间倒序排列


下一篇:使用3dmax 9.0导入Illustrator 文件时提示"Line in file exceeds 255 characters"