先来看些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
服务端
- 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);
- }
- }