來源:Carson_Ho 發(fā)布時(shí)間:2018-11-24 09:53:53 閱讀量:1218
前言
JDK 1.4后,Java提供了一個(gè)全新的IO API,即 Java New IO
本文 全面 & 詳細(xì)解析Java New IO,希望你們會(huì)喜歡
目錄
儲(chǔ)備知識(shí):Java IO
1. 定義
即 Java New IO
是1個(gè)全新的、 JDK 1.4后提供的 IO API
2. 作用
提供了與標(biāo)準(zhǔn)IO不同的IO工作方式
可替代 標(biāo)準(zhǔn)Java IO 的IO API
3. 新特性
對(duì)比于 Java IO,NIO具備的新特性如下
4. 核心組件
Java NIO的核心組件 包括:
通道(Channel)
緩沖區(qū)(Buffer)
選擇器(Selectors)
下面將詳細(xì)介紹:
5. 具體使用
5.1 基于通道 & 緩沖數(shù)據(jù)
具體步驟如下:
// 1. 獲取數(shù)據(jù)源 和 目標(biāo)傳輸?shù)氐妮斎胼敵隽鳎ù颂幰詳?shù)據(jù)源 = 文件為例)
FileInputStream fin = new FileInputStream(infile);
FileOutputStream fout = new FileOutputStream(outfile);
// 2. 獲取數(shù)據(jù)源的輸入輸出通道
FileChannel fcin = fin.getChannel();
FileChannel fcout = fout.getChannel();
// 3. 創(chuàng)建 緩沖區(qū) 對(duì)象:Buffer(共有2種方法)
// 方法1:使用allocate()靜態(tài)方法
ByteBuffer buff = ByteBuffer.allocate(256);
// 上述方法創(chuàng)建1個(gè)容量為256字節(jié)的ByteBuffer
// 注:若發(fā)現(xiàn)創(chuàng)建的緩沖區(qū)容量太小,則重新創(chuàng)建一個(gè)大小合適的緩沖區(qū)
// 方法2:通過包裝一個(gè)已有的數(shù)組來創(chuàng)建
// 注:通過包裝的方法創(chuàng)建的緩沖區(qū)保留了被包裝數(shù)組內(nèi)保存的數(shù)據(jù)
ByteBuffer buff = ByteBuffer.wrap(byteArray);
// 額外:若需將1個(gè)字符串存入ByteBuffer,則如下
String sendString="你好,服務(wù)器. ";
ByteBuffer sendBuff = ByteBuffer.wrap(sendString.getBytes("UTF-16"));
// 4. 從通道讀取數(shù)據(jù) & 寫入到緩沖區(qū)
// 注:若 以讀取到該通道數(shù)據(jù)的末尾,則返回-1
fcin.read(buff);
// 5. 傳出數(shù)據(jù)準(zhǔn)備:將緩存區(qū)的寫模式 轉(zhuǎn)換->> 讀模式
buff.flip();
// 6. 從 Buffer 中讀取數(shù)據(jù) & 傳出數(shù)據(jù)到通道
fcout.write(buff);
// 7. 重置緩沖區(qū)
// 目的:重用現(xiàn)在的緩沖區(qū),即 不必為了每次讀寫都創(chuàng)建新的緩沖區(qū),在再次讀取之前要重置緩沖區(qū)
// 注:不會(huì)改變緩沖區(qū)的數(shù)據(jù),只是重置緩沖區(qū)的主要索引值
buff.clear();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
5.2 基于選擇器(Selecter)
具體步驟如下:
// 1. 創(chuàng)建Selector對(duì)象
Selector sel = Selector.open();
// 2. 向Selector對(duì)象綁定通道
// a. 創(chuàng)建可選擇通道,并配置為非阻塞模式
ServerSocketChannel server = ServerSocketChannel.open();
server.configureBlocking(false);
// b. 綁定通道到指定端口
ServerSocket socket = server.socket();
InetSocketAddress address = new InetSocketAddress(port);
socket.bind(address);
// c. 向Selector中注冊(cè)感興趣的事件
server.register(sel, SelectionKey.OP_ACCEPT);
return sel;
// 3. 處理事件
try {
while(true) {
// 該調(diào)用會(huì)阻塞,直到至少有一個(gè)事件就緒、準(zhǔn)備發(fā)生
selector.select();
// 一旦上述方法返回,線程就可以處理這些事件
Set<SelectionKey> keys = selector.selectedKeys();
Iterator<SelectionKey> iter = keys.iterator();
while (iter.hasNext()) {
SelectionKey key = (SelectionKey) iter.next();
iter.remove();
process(key);
}
}
} catch (IOException e) {
e.printStackTrace();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
6. 實(shí)例講解
實(shí)例說明:實(shí)現(xiàn)文件復(fù)制功能
實(shí)現(xiàn)方式:通道FileChannel、 緩沖區(qū)ByteBuffer
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
public class Test {
public static void main(String[] args) throws IOException {
// 設(shè)置輸入源 & 輸出地 = 文件
String infile = "C:\\copy.sql";
String outfile = "C:\\copy.txt";
// 1. 獲取數(shù)據(jù)源 和 目標(biāo)傳輸?shù)氐妮斎胼敵隽鳎ù颂幰詳?shù)據(jù)源 = 文件為例)
FileInputStream fin = new FileInputStream(infile);
FileOutputStream fout = new FileOutputStream(outfile);
// 2. 獲取數(shù)據(jù)源的輸入輸出通道
FileChannel fcin = fin.getChannel();
FileChannel fcout = fout.getChannel();
// 3. 創(chuàng)建緩沖區(qū)對(duì)象
ByteBuffer buff = ByteBuffer.allocate(1024);
while (true) {
// 4. 從通道讀取數(shù)據(jù) & 寫入到緩沖區(qū)
// 注:若 以讀取到該通道數(shù)據(jù)的末尾,則返回-1
int r = fcin.read(buff);
if (r == -1) {
break;
}
// 5. 傳出數(shù)據(jù)準(zhǔn)備:調(diào)用flip()方法
buff.flip();
// 6. 從 Buffer 中讀取數(shù)據(jù) & 傳出數(shù)據(jù)到通道
fcout.write(buff);
// 7. 重置緩沖區(qū)
buff.clear();
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
7. 與Java IO的區(qū)別
在線
客服
服務(wù)時(shí)間:周一至周日 08:30-18:00
選擇下列產(chǎn)品馬上在線溝通:
客服
熱線
7*24小時(shí)客服服務(wù)熱線
關(guān)注
微信
關(guān)注官方微信