一、通道(Channel):由 java.nio.channels 包定義的。Channel 表示 IO 源與目标打開的連接配接。Channel 類似于傳統的“流”。隻不過 Channel本身不能直接通路資料,Channel 隻能與Buffer 進行互動。
二、Channel重要實作
- FileChannel:操作檔案的讀寫
- SocketChannel:通過TCP讀寫網絡資料
- ServerSocketChannel:監聽TCP連接配接,你能利用它建立一個最簡單的Web伺服器
- DatagramChannel:通過UDP讀寫網絡資料
三、FileChannel 的檔案讀寫
1)利用FileChannel 本身提供的transferTo進行資料的讀寫。
package com.troy.nio.application;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.nio.channels.FileChannel;
public class Channel {
public static void main(String[] args) throws Exception {
//讀取檔案
FileInputStream fileInputStream = new FileInputStream("d:/t.txt");
//寫出檔案
FileOutputStream fileOutputStream = new FileOutputStream("d:/e.txt");
//擷取讀取通道
FileChannel inChannel = fileInputStream.getChannel();
//擷取寫入通道
FileChannel outChannel = fileOutputStream.getChannel();
//完成資料的寫入
inChannel.transferTo(0,inChannel.size(),outChannel);
}
}
2)利用FileChannel 提供的讀寫方法
package com.troy.nio.application;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
public class Channel {
public static void main(String[] args) throws Exception {
//讀取檔案
FileInputStream fileInputStream = new FileInputStream("d:/t.txt");
//寫出檔案
FileOutputStream fileOutputStream = new FileOutputStream("d:/e.txt");
//擷取讀取通道
FileChannel inChannel = fileInputStream.getChannel();
//擷取寫入通道
FileChannel outChannel = fileOutputStream.getChannel();
//緩存
ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
//讀取資料
while (inChannel.read(byteBuffer) != -1) {
//轉換成可讀寫
byteBuffer.flip();
System.out.println(new String(byteBuffer.array(),"GBK").trim());
//寫出資料,清楚緩存
outChannel.write(byteBuffer);
byteBuffer.clear();
}
}
}
四、SocketChannel和ServerSocketChannel在同時使用時,都是tcp協定進行傳輸的,在使用上面比較服務具體的協定控制
具體的應用可以參考:
http://www.cnblogs.com/ll409546297/p/7929646.html五、DatagramChannel的方式
1)用戶端
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.DatagramChannel;
public class UDPClient {
public static void main(String[] args) throws Exception {
//擷取UDP通道
DatagramChannel datagramChannel = DatagramChannel.open();
//設定非阻塞
datagramChannel.configureBlocking(false);
//發送資料
datagramChannel.send(ByteBuffer.wrap("hello server!".getBytes()),new InetSocketAddress("localhost",9000));
}
}
2)服務端的2中寫法,阻塞和非阻塞
1、阻塞
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.DatagramChannel;
public class UDPServer {
//UDP通道
private static DatagramChannel datagramChannel;
public static void main(String[] args) throws Exception {
serverInit();
listen();
}
//初始化
private static void serverInit() throws IOException {
//擷取UDP通道
datagramChannel = DatagramChannel.open();
//設定接收端口
datagramChannel.socket().bind(new InetSocketAddress(9000));
}
//監聽
private static void listen() throws IOException {
while (true) {
//接收的長度
ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
//這裡會阻塞
datagramChannel.receive(byteBuffer);
byteBuffer.flip();
System.out.println(new String(byteBuffer.array()).trim());
}
}
}
2、非阻塞,利用selector來進行資料選擇
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.DatagramChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.util.Iterator;
public class UDPServer {
//選擇器
private static Selector selector;
//UDP通道
private static DatagramChannel datagramChannel;
public static void main(String[] args) throws Exception {
serverInit();
listen();
}
//初始化
private static void serverInit() throws IOException {
//擷取選擇器
selector = Selector.open();
//擷取UDP通道
datagramChannel = DatagramChannel.open();
//設定非阻塞
datagramChannel.configureBlocking(false);
//設定接收端口
datagramChannel.socket().bind(new InetSocketAddress(9000));
//注冊
datagramChannel.register(selector, SelectionKey.OP_READ);
}
//監聽
private static void listen() throws IOException {
while (true) {
selector.select();
Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
while (iterator.hasNext()) {
SelectionKey selectionKey = iterator.next();
if (selectionKey.isReadable()) {
//接收的長度
ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
//這裡不會阻塞
datagramChannel.receive(byteBuffer);
byteBuffer.flip();
System.out.println(new String(byteBuffer.array()).trim());
}
}
}
}
}
六、基本上channel的實作用法就這些了,但是裡面會涉及到很多細節的用法,這個需要自己進一步研究