下面的例子,说明了,nio中的三大核心类的基本使用。buffer,channel,selector

 package com.shengsiyuan.nio;

 import org.junit.Test;

 import java.io.*;
import java.net.*;
import java.nio.ByteBuffer;
import java.nio.IntBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.*;
import java.nio.channels.spi.SelectorProvider;
import java.security.SecureRandom;
import java.util.Arrays;
import java.util.Iterator;
import java.util.Set; public class NioTest1 { public static void main(String[] args) {
IntBuffer intBuffer = IntBuffer.allocate(10); for (int i = 0; i < intBuffer.capacity(); i++) {
int randomNumber = new SecureRandom().nextInt(20);
intBuffer.put(randomNumber);
} intBuffer.flip();//翻转,从写转到读状态 while (intBuffer.hasRemaining()) {
System.out.println(intBuffer.get());
} } public void testBuffer() {
IntBuffer intBuffer = IntBuffer.allocate(10); for (int i = 0; i < intBuffer.capacity(); i++) {
int randomNumber = new SecureRandom().nextInt(20);
intBuffer.put(randomNumber);
} intBuffer.flip();//翻转,从写转到读状态 while (intBuffer.hasRemaining()) {
System.out.println(intBuffer.get());
}
} /**
* @ClassName: NioTest1
* @Description: 描述 读文件
* @Author:
* @CreateDate: 2019/8/27 21:26
* @Version: 1.0
*/
@Test
public void testChannelRead() {
try {
FileInputStream fileInputStream = new FileInputStream("NioTest1.txt"); FileChannel fileChannel = fileInputStream.getChannel(); ByteBuffer byteBuffer = ByteBuffer.allocate(512); fileChannel.read(byteBuffer); byteBuffer.flip(); while(byteBuffer.remaining() > 0) { byte b = byteBuffer.get();
System.out.println("char is : " + (char) b); if((char)b == 'e') {
byteBuffer.mark();
}
} System.out.println(byteBuffer.position());
System.out.println(byteBuffer.limit());
System.out.println(byteBuffer.capacity()); byteBuffer.reset(); // System.out.println(byteBuffer.mark());
System.out.println(byteBuffer.position());
System.out.println(byteBuffer.limit());
System.out.println(byteBuffer.capacity()); fileChannel.close();
fileInputStream.close(); } catch (Exception e) {
e.printStackTrace();
}
} /**
* @ClassName: NioTest1
* @Description: 描述 写文件
* @Author:
* @CreateDate: 2019/8/27 21:25
* @Version: 1.0
*/
@Test
public void testChannelWrite() {
try{
FileInputStream fileInputStream = new FileInputStream("NioTest1.txt");
FileChannel fileChannel = fileInputStream.getChannel(); FileChannel randowFileChannel = new RandomAccessFile(new File("NioTest1.txt"),"rw").getChannel(); ByteBuffer byteBuffer = ByteBuffer.allocate(512); byte[] byteArr = "hello nio nihao!".getBytes(); byteBuffer.put(byteArr); byteBuffer.flip(); // fileChannel.write(byteBuffer); randowFileChannel.write(byteBuffer);
}catch (Exception e) {
e.printStackTrace();
}
} /**
* @ClassName: NioTest1
* @Description: 描述 读写文件
* @Author:
* @CreateDate: 2019/8/27 21:25
* @Version: 1.0
*/
@Test
public void testChannelReadAndWrite() {
try {
FileInputStream fileInputStream = new FileInputStream("input.txt");
FileOutputStream fileOutputStream = new FileOutputStream("out.txt"); FileChannel inputFileChannel = fileInputStream.getChannel();
FileChannel outputFileChannel = fileOutputStream.getChannel(); ByteBuffer byteBuffer = ByteBuffer.allocate(512); while(inputFileChannel.read(byteBuffer) != -1) { byteBuffer.flip(); outputFileChannel.write(byteBuffer); // byteBuffer.clear();
} }catch (Exception e) {
e.printStackTrace();
} } /**
* @ClassName: NioTest1
* @Description: 描述 切下部分的byteBuffer 作为一个快照,可以实现同步
* @Author:
* @CreateDate: 2019/8/27 21:24
* @Version: 1.0
*/
@Test
public void testSlice() {
try{
ByteBuffer byteBuffer = ByteBuffer.allocate(512); for (int i = 0; i < 20; i++) {
byteBuffer.put((byte)i);
}
// byteBuffer.flip(); ByteBuffer newByteBuffer = byteBuffer.slice(); byteBuffer.put((byte)'a');
byteBuffer.put((byte)'b'); // newByteBuffer.flip();
System.out.println(newByteBuffer.get(0)); // byteBuffer.put(0, (byte)9); newByteBuffer.put(0, (byte)9); System.out.println(byteBuffer.get(20)); System.out.println(newByteBuffer.get(0)); }catch (Exception e) {
e.printStackTrace();
}
} /**
* @ClassName: NioTest1
* @Description: 描述 只读的byteBuffer
* @Author:
* @CreateDate: 2019/8/27 21:24
* @Version: 1.0
*/
@Test
public void testReadonlyBuffer() { ByteBuffer byteBuffer = ByteBuffer.allocate(512);
for (int i = 0; i < 10; i++) {
byteBuffer.put((byte)i);
} ByteBuffer readOnlyBuffer = byteBuffer.asReadOnlyBuffer(); readOnlyBuffer.position(0); readOnlyBuffer.put((byte)1); } /**
* @ClassName: NioTest1
* @Description: 描述 通过直接内存,零拷贝来处理文件
* @Author:
* @CreateDate: 2019/8/27 21:23
* @Version: 1.0
*/
@Test
public void testChannelReadAndWriteDirect() {
try {
FileInputStream fileInputStream = new FileInputStream("input.txt");
FileOutputStream fileOutputStream = new FileOutputStream("out.txt"); FileChannel inputFileChannel = fileInputStream.getChannel();
FileChannel outputFileChannel = fileOutputStream.getChannel(); ByteBuffer byteBuffer = ByteBuffer.allocateDirect(512); while(inputFileChannel.read(byteBuffer) != -1) { byteBuffer.flip(); outputFileChannel.write(byteBuffer); byteBuffer.clear();
} }catch (Exception e) {
e.printStackTrace();
} } /**
* @ClassName: NioTest1 内存映射,来修改文件 而不操作buffer
* @Description: 描述
* @Author:
* @CreateDate: 2019/8/27 21:23
* @Version: 1.0
*/
@Test
public void testMapBuffer() throws Exception {
RandomAccessFile randomAccessFile = new RandomAccessFile("NioTest1.txt", "rw");
FileChannel fileChannel = randomAccessFile.getChannel(); MappedByteBuffer mappedByteBuffer = fileChannel.map(FileChannel.MapMode.READ_WRITE, 0, 5); mappedByteBuffer.put(0, (byte)'a');
mappedByteBuffer.put(3, (byte)'b'); fileChannel.close();
randomAccessFile.close();
} /**
* @ClassName: NioTest1
* @Description: 描述 测试 filelock
* @Author:
* @CreateDate: 2019/8/27 21:30
* @Version: 1.0
*/
@Test
public void testFilelock() throws Exception {
FileChannel fileChannel = new RandomAccessFile("NioTest1.txt", "rw").getChannel(); FileLock fileLock = fileChannel.lock(3, 6, false); System.out.println(fileLock.isValid());
System.out.println(fileLock.isShared());
} /**
* @ClassName: NioTest1
* @Description: 描述
* @Author:
* @CreateDate: 2019/8/27 22:36
* @Version: 1.0
*/
@Test
public void testScattering() throws Exception {
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
SocketAddress address = new InetSocketAddress(8899);
serverSocketChannel.bind(address); SocketChannel socketChannel = serverSocketChannel.accept(); int messageLength = 2 + 3 +4;
ByteBuffer[] byteBuffers = new ByteBuffer[3]; byteBuffers[0] = ByteBuffer.allocate(2);
byteBuffers[1] = ByteBuffer.allocate(3);
byteBuffers[2] = ByteBuffer.allocate(4); while(true) {
long readLength = 0; //最大读取 messageLength 长度的字符
while(readLength < messageLength ) {
long r = socketChannel.read(byteBuffers);
readLength += r; System.out.println("byteBuffer length r is " + r);
System.out.println("readLength length r is " + readLength); Arrays.asList(byteBuffers).forEach(byteBuffer -> {
System.out.println("p:" + byteBuffer.position() + ", l: " +byteBuffer.limit());
});
} Arrays.asList(byteBuffers).forEach(byteBuffer -> {
byteBuffer.flip();
}); long writeLength = 0;
//写会去
while(writeLength < messageLength) {
long w = socketChannel.write(byteBuffers);
writeLength += w;
System.out.println("byteBuffer length w is " + w);
System.out.println("writeLength length w is " + writeLength); Arrays.asList(byteBuffers).forEach(byteBuffer -> {
System.out.println("p:" + byteBuffer.position() + ", l: " +byteBuffer.limit());
});
} Arrays.asList(byteBuffers).forEach(byteBuffer -> byteBuffer.clear()); }
} @Test
public void testSelector() throws Exception{
Selector selector = Selector.open(); int[] ports = {5000, 5001, 5002, 5003, 5004}; for (int i = 0; i < ports.length; i++) {
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
serverSocketChannel.configureBlocking(false); //变成非阻塞的模式 很重要 // serverSocketChannel.bind(new InetSocketAddress(ports[i])); ServerSocket serverSocket = serverSocketChannel.socket();
//这个bind 直接绑在 serverSocketChannel 可以不 尝试了下,好像区别不大,都可以走通 但是不能重复绑
serverSocket.bind(new InetSocketAddress(ports[i])); serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT); System.out.println("监听:" + ports[i]);
} while(true) { int number = selector.select();
System.out.println("number:" + number); Set<SelectionKey> selectionKeys = selector.selectedKeys(); Iterator<SelectionKey> keyIterable = selectionKeys.iterator(); System.out.println("selectionKeys : " + selectionKeys); while(keyIterable.hasNext()) {
SelectionKey selectionKey = keyIterable.next();
if(selectionKey.isAcceptable()) {//可接受的
ServerSocketChannel serverSocketChannel = (ServerSocketChannel) selectionKey.channel();
//这里为什么还要调accept 因为上面放进去的就是 ServerSocketChannel ,而且没有调accept 接收请求
SocketChannel socketChannel = serverSocketChannel.accept();
socketChannel.configureBlocking(false); System.out.println("获得链接:" + socketChannel); socketChannel.register(selector, SelectionKey.OP_READ);
// socketChannel.register(selector, SelectionKey.OP_READ); 重复注册好像不影响 keyIterable.remove();//如果不remove selectionKeys中会一直存在事件对象
} else if(selectionKey.isReadable()) {//可读取的
//这里就可以直接用SocketChannel来接收,因为在accept中,是用socketChannel来注册的
SocketChannel socketChannel = (SocketChannel) selectionKey.channel(); ByteBuffer byteBuffer = ByteBuffer.allocate(512);
while(socketChannel.read(byteBuffer) > 0) {
byteBuffer.flip(); System.out.println("读取到客户端的消息:" + byteBuffer);
System.out.println("读取到客户端:" + socketChannel); socketChannel.write(byteBuffer); byteBuffer.clear();
} keyIterable.remove(); } } } }
}
05-12 11:26