NIO簡單應用
使用FileChannel完成文件複製
public class FileNIOCopyDemo {
public static void main(String[] args) {
nioCopyResourceFile();
}
/**
* 複製兩個資源目錄下的文件
*/
private static void nioCopyResourceFile() {
String sourcePath = NioDemoConfig.sourcePath;
String destPath = NioDemoConfig.destPath;
nioCopyFile(sourcePath, destPath);
}
private static void nioCopyFile(String sourcePath, String destPath) {
File srcFile = new File(sourcePath);
File destFile = new File(destPath);
try {
if (!destFile.exists()) {
destFile.createNewFile();
}
long startTime = System.currentTimeMillis();
FileInputStream fis = null;
FileOutputStream fos = null;
FileChannel inChannel = null;
FileChannel outChannel = null;
try {
fis = new FileInputStream(srcFile);
fos = new FileOutputStream(destFile);
inChannel = fis.getChannel();
outChannel = fos.getChannel();
ByteBuffer buffer = ByteBuffer.allocate(1024);
int length = 0;
int outlength = 0;
//從讀通道讀取數據到buffer
while ((length = inChannel.read(buffer)) != -1) {
//切換buffer至讀模式
buffer.flip();
//將buffer內容寫入輸出channel
while ((outlength = outChannel.write(buffer)) != 0) {
System.out.println("寫入的字節數: " + outlength);
}
//切換buffer爲寫模式
buffer.clear();
}
//強制刷新到磁盤
outChannel.force(true);
} finally {
closeUtil(outChannel);
closeUtil(inChannel);
closeUtil(fos);
closeUtil(fis);
Long endTime = System.currentTimeMillis();
System.out.println("複製花費毫秒數: " + (endTime - startTime));
}
} catch (IOException e) {
e.printStackTrace();
}
}
private static void closeUtil(Closeable item) {
if (item != null) {
try {
item.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
使用SocketChannel發送文件
客戶端發送
public class NioSendClient {
private Charset charset = Charset.forName("UTF-8");
public static void main(String[] args) {
NioSendClient client = new NioSendClient();//啓動客戶端連接
client.sendFile();//傳輸文件
}
/**
* 向服務器傳輸文件
*/
private void sendFile() {
try {
//獲取源文件、目的文件路徑
String srcPath = NioDemoConfig.sourcePath;
String destPath = NioDemoConfig.destPath;
//獲取源文件File對象
File srcFile = new File(srcPath);
if (!srcFile.exists()) {
System.out.println("文件不存在");
return;
}
//獲取源文件流
FileInputStream fileInputStream = new FileInputStream(srcFile);
//獲取源文件通道
FileChannel fileChannel = fileInputStream.getChannel();
//獲取Socket通道
SocketChannel socketChannel = SocketChannel.open();
//連接服務端
socketChannel.connect(new InetSocketAddress(NioDemoConfig.SOCKET_SERVER_IP, NioDemoConfig.SOCKET_SERVER_PORT));
//設置channel爲非阻塞
socketChannel.configureBlocking(false);
//自旋,等待連接完成
while (!socketChannel.finishConnect()) {
//不斷自旋、等待,或者做一些其他操作
}
System.out.println("Client成功連接服務器端");
//發送文件名稱
ByteBuffer fileNameByteBuffer = charset.encode(destPath);
socketChannel.write(fileNameByteBuffer);
//發送文件長度
ByteBuffer buffer = ByteBuffer.allocate(NioDemoConfig.SEND_BUFFER_SIZE);
buffer.putLong(srcFile.length());
buffer.flip();
socketChannel.write(buffer);
buffer.clear();
//發送文件內容
System.out.println("開始傳輸文件");
int length = 0;
long progress = 0;
while ((length = fileChannel.read(buffer)) > 0) {
buffer.flip();
socketChannel.write(buffer);
buffer.clear();
progress += length;
System.out.println("| " + (100 * progress / srcFile.length()) + "% |");
}
//判斷文件傳輸結束,發送結束符至對端
if (length == -1) {
closeUtil(fileChannel);
//在SocketChannel傳輸通道關閉前,儘量發送一個輸出結果標誌到對端
socketChannel.shutdownOutput();
closeUtil(socketChannel);
}
System.out.println("====== 文件傳輸成功 =======");
} catch (Exception e) {
e.printStackTrace();
}
}
private static void closeUtil(Closeable item) {
if (item != null) {
try {
item.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
使用DatagramChannel數據報通道發送數據
客戶端
public class UDPClient {
public static void main(String[] args) throws IOException {
new UDPClient().send();
}
public void send() throws IOException {
//獲取DatagramChannel數據報通道
DatagramChannel channel = DatagramChannel.open();
//設置爲非阻塞
channel.configureBlocking(false);
//創建ByteBuffer
ByteBuffer buffer = ByteBuffer.allocate(NioDemoConfig.SEND_BUFFER_SIZE);
//掃描輸入
Scanner scanner = new Scanner(System.in);
//遍歷掃描到的內容,發送數據
while (scanner.hasNext()) {
String next = scanner.next();
buffer.put(next.getBytes());
channel.send(buffer, new InetSocketAddress(NioDemoConfig.SOCKET_SERVER_IP, NioDemoConfig.SOCKET_SERVER_PORT));
buffer.clear();
}
//關閉數據報通道
channel.close();
}
}
服務端
public class UDPServer {
public static void main(String[] args) throws IOException {
new UDPServer().receive();
}
public void receive() throws IOException {
//獲取數據報通道
DatagramChannel channel = DatagramChannel.open();
//設置爲非阻塞
channel.configureBlocking(false);
//綁定監聽地址
channel.socket().bind(new InetSocketAddress(NioDemoConfig.SOCKET_SERVER_IP, NioDemoConfig.SOCKET_SERVER_PORT));
//開啓一個通道選擇器
Selector selector = Selector.open();
//將通道註冊到選擇器
channel.register(selector, SelectionKey.OP_READ);
//通過選擇器,查詢IO事件
while (selector.select() > 0) {
Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
ByteBuffer buffer = ByteBuffer.allocate(NioDemoConfig.SEND_BUFFER_SIZE);
//迭代IO事件
while (iterator.hasNext()) {
SelectionKey selectionKey = iterator.next();
//可讀事件,有事件到來
if (selectionKey.isReadable()) {
//讀取數據報通道的數據
SocketAddress client = channel.receive(buffer);
buffer.flip();
System.out.println(new String(buffer.array(), 0, buffer.limit()));
buffer.clear();
}
}
iterator.remove();
}
}
}
參考資料:《Netty、Redis、Zookeeper高併發實戰》