参考
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() {
@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 selectionKeys=selector.selectedKeys();
Iterator 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(){
@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);
}
}