1. FileChannel写入文件
package com.mycom.test.nio; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; /** * FileChannel写入文件 * * @author guweiqiang */ public class TestFileChannelWrite { public static void main(String[] args) { try { // 新建一个File对象 File file = new File("e:/writeData.txt"); // 将文件读取到文件输出流中 FileOutputStream outputStream = new FileOutputStream(file); // 获取FileChannel通道对象 FileChannel fileChannel = outputStream.getChannel(); // 新建缓冲区 ByteBuffer buffer = ByteBuffer.allocate(1024); String testStr = "hello world!"; // 将内容写入到缓冲区 buffer.put(testStr.getBytes()); buffer.flip(); //此处必须要调用buffer的flip方法 // 将缓冲区内容写入到fileChannel通道 fileChannel.write(buffer); // 关闭fileChannel通道 fileChannel.close(); // 关闭文件输出流 outputStream.close(); } catch (IOException e) { e.printStackTrace(); } } }
2. FileChannel读取文件
package com.mycom.test.nio; import java.io.IOException; import java.io.RandomAccessFile; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; /** * FileChannel读取文件 * * @author guweiqiang */ public class TestFileChannelRead { @SuppressWarnings("resource") public static void main(String[] args) { try { // 新建一个RandomAccessFile对象 RandomAccessFile file = new RandomAccessFile("e:/readData.txt", "rw"); // rw表示以读写方式打开文件,r表示只读方式打开 // 获取FileChannel通道对象 FileChannel fileChannel = file.getChannel(); // 新建缓冲区 ByteBuffer buffer = ByteBuffer.allocate(1024); // 将fileChannel中的数据读取到buffer中 fileChannel.read(buffer); // 再将buffer中的数据读取到String对象中 byte[] data = buffer.array(); String ss = new String(data).trim(); System.out.println(ss); // 关闭fileChannel通道 fileChannel.close(); } catch (IOException e) { e.printStackTrace(); } } }
(前提是存在以下文件:e:/readData.txt)
3. Server与Cilent通信
NIO 服务端:
package com.mycom.test.nio; import java.io.IOException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; import java.nio.channels.ServerSocketChannel; import java.nio.channels.SocketChannel; import java.util.Iterator; /** * NIO 服务端 * * @author guweiqiang */ public class NIOServer { // 通道管理器 private Selector selector; /** * 获取一个服务端通道ServerSocket,并进行初始化 */ public void initServer(int port) throws IOException{ // 获取一个ServerSocket服务端通道 ServerSocketChannel serverChannel = ServerSocketChannel.open(); // 设置通道为非阻塞模式 serverChannel.configureBlocking(false); // 绑定端口 serverChannel.socket().bind(new InetSocketAddress(port)); // 获取一个通道管理器 this.selector = Selector.open(); // 将通道管理器和通道进行绑定,并为该通道注册SelectionKey.OP_ACCEPT事件 // 当事件到达时,selector.select()就会返回;如果事件没有到达,则selector.select()就会一直阻塞 serverChannel.register(selector, SelectionKey.OP_ACCEPT); } /** * 采用轮询的方式监听selector上是否有需要处理的事件,如果有则进行处理 */ @SuppressWarnings("rawtypes") public void listen() throws IOException{ System.out.println("服务端启动成功!"); // 轮询访问selector while(true){ // 当有已注册的事件到达时,方法返回,否则就一直阻塞到有注册的事件到达为止 selector.select(); // 获取selector中选中项的迭代器,选中项为注册的事件 Iterator it = this.selector.selectedKeys().iterator(); while(it.hasNext()){ SelectionKey key = (SelectionKey)it.next(); // 删除已选的key,防止重复处理 it.remove(); if(key.isAcceptable()){ // 有客户端请求连接的事件 // 获取服务端通道 ServerSocketChannel serverChannel = (ServerSocketChannel)key.channel(); // 获取与客户端连接的通道 SocketChannel clientChannel = serverChannel.accept(); // 设置为非阻塞 clientChannel.configureBlocking(false); // 给客户端发送消息 clientChannel.write(ByteBuffer.wrap(new String("hello client, i'm server!").getBytes("utf-8"))); // 在和客户端连接成功之后,为了可以接收到客户端的消息,需要给通道设置读权限 clientChannel.register(this.selector, SelectionKey.OP_READ); } else if(key.isReadable()){ // 有读取事件发生 readKey(key); } } } } /** * 处理读取客户端发来的消息 */ private void readKey(SelectionKey key) throws IOException { // 服务器可读取消息:得到事件发生的Socket通道 SocketChannel channel = (SocketChannel)key.channel(); // 读取通道里的消息 ByteBuffer buffer = ByteBuffer.allocate(1024); channel.read(buffer); byte[] data = buffer.array(); String receivedMsg = new String(data).trim(); System.out.println("服务端收到客户端发来的的消息:" + receivedMsg); // 向通道写入消息 String sendMsg = "hello client!"; ByteBuffer outBuffer = ByteBuffer.wrap(sendMsg.getBytes("utf-8")); channel.write(outBuffer);// 将消息回送给客户端 } /** * 启动服务端测试 */ public static void main(String[] args) { try { NIOServer server = new NIOServer(); server.initServer(8000); server.listen(); } catch (IOException e) { e.printStackTrace(); } } }
NIO 客户端:
package com.mycom.test.nio; import java.io.IOException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; import java.nio.channels.SocketChannel; import java.util.Iterator; /** * NIO 客户端 * * @author guweiqiang */ public class NIOClient { // 通道管理器 private Selector selector; /** * 获取一个客户端通道,并进行初始化 * @throws IOException */ public void initClient(String ip, int port) throws IOException{ // 获取一个Socket客户端通道 SocketChannel clientChannel = SocketChannel.open(); // 设置通道为非阻塞模式 clientChannel.configureBlocking(false); // 获取一个通道管理器 this.selector = Selector.open(); // 客户端连接服务器 clientChannel.connect(new InetSocketAddress(ip, port)); // 将通道管理器和通道进行绑定,并为该通道注册SelectionKey.OP_CONNECT事件 clientChannel.register(selector, SelectionKey.OP_CONNECT); } /** * 采用轮询的方式监听selector上是否有需要处理的事件,如果有则进行处理 */ @SuppressWarnings("rawtypes") public void listen() throws IOException{ // 轮询访问selector while(true){ // 当有已注册的事件到达时,方法返回,否则就一直阻塞到有注册的事件到达为止 selector.select(); // 获取selector中选中项的迭代器,选中项为注册的事件 Iterator it = this.selector.selectedKeys().iterator(); while(it.hasNext()){ SelectionKey key = (SelectionKey)it.next(); // 删除已选的key,防止重复处理 it.remove(); if(key.isConnectable()){ // 有连接事件发生 // 获取客户端通道 SocketChannel clientChannel = (SocketChannel)key.channel(); // 如果正在连接,则设置连接完成 if(clientChannel.isConnectionPending()){ clientChannel.finishConnect(); } // 设置通道为非阻塞模式 clientChannel.configureBlocking(false); // 给服务端发送消息 clientChannel.write(ByteBuffer.wrap(new String("hello server, i'm client!").getBytes("utf-8"))); // 在和服务端连接之后,为了可以接收到服务端的消息,需要给客户端设置读权限 clientChannel.register(selector, SelectionKey.OP_READ); } else if(key.isReadable()){ // 有读取事件发生 this.readKey(key); } } } } /** * 处理读取服务端发来的消息 */ private void readKey(SelectionKey key) throws IOException { // 服务器可读取消息:得到事件发生的Socket通道 SocketChannel channel = (SocketChannel)key.channel(); // 读取通道里的消息 ByteBuffer buffer = ByteBuffer.allocate(1024); channel.read(buffer); byte[] data = buffer.array(); String receivedMsg = new String(data).trim(); System.out.println("客户端收到服务端发来的消息:" + receivedMsg); // 向通道写入消息 String sendMsg = "hello server!"; ByteBuffer outBuffer = ByteBuffer.wrap(sendMsg.getBytes("utf-8")); channel.write(outBuffer);// 将消息回送给服务端 } /** * 启动客户端测试 */ public static void main(String[] args) { try { NIOClient client = new NIOClient(); client.initClient("127.0.0.1", 8000); client.listen(); } catch (IOException e) { e.printStackTrace(); } } }