java nio 异步操作 (一)

    xiaoxiao2025-09-12  80

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

    相关的图片

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

    文件通道  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

    服务端

    [java] view plain copy 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==0continue;              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("注册的可写");      }              }  

    客户端

    [java] view plain copy 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

    [java] view plain copy 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

    [java] view plain copy 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

    [java] view plain copy 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);      }          }  

    相关资源:python入门教程(PDF版)
    最新回复(0)