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