筆者以前接觸的NIO編程比較少,因此對這一塊的基礎也比較弱,NIO做爲java編程中一個重要的模塊,不能很好的掌握它,感受本身在java方面就掌握的不夠,因此,接下來,筆者會學習NIO編程,因此,該系列文章不會涉及到很深源碼解析,純粹的是學習課程,也能夠理解爲筆者的筆記,記錄學習NIO的過程,同時也但願這類文章能夠對一樣想掌握NIO編程的你有幫助。html
Java NIO(New IO)是一個能夠替代標準Java IO API的IO API(從Java 1.4開始),Java NIO提供了與標準IO不一樣的IO工做方式。NIO能夠理解爲非阻塞IO,傳統的IO的read和write只能阻塞執行,線程在讀寫IO期間不能幹其餘事情,好比調用socket.read()時,若是服務器一直沒有數據傳輸過來,線程就一直阻塞,而NIO中能夠配置socket爲非阻塞模式。java
Channel(通道)編程
Java NIO的通道相似流,但又有些不一樣:bash
既能夠從通道中讀取數據,又能夠寫數據到通道。但流的讀寫一般是單向的。 通道能夠異步地讀寫。服務器
通道中的數據老是要先讀到一個Buffer,或者老是要從一個Buffer中寫入。網絡
Channel的實現app
這些是Java NIO中最重要的通道的實現:dom
FileChannel: 從文件中讀寫數據。異步
DatagramChannel : 能經過UDP讀寫網絡中的數據。socket
SocketChannel: 能經過TCP讀寫網絡中的數據。
ServerSocketChannel :能夠監聽新進來的TCP鏈接,像Web服務器那樣。對每個新進來的鏈接都會建立一個SocketChannel。
Buffer(緩衝區)
緩衝區本質上是一塊能夠寫入數據,而後能夠從中讀取數據的內存。這塊內存被包裝成NIO Buffer對象,並提供了一組方法,用來方便的訪問該塊內存。
Buffer(緩衝區)的主要屬性
屬性 | 功能 |
---|---|
capacity | 容量 |
position | 緩衝區當前位置指針,最大可爲capacity – 1 |
limit | 緩衝區最大讀取和寫入限制 |
buffer屬性示意圖:
上圖展現了寫模式和讀模式下,以上屬性的示意圖,寫模式下,limit和capacity是同樣的,這表示你能寫入的最大容量數據,讀模式下,limit會和position同樣,表示你能讀到寫入的所有數據。
Buffer(緩衝區)的主要分類
其實以上基本上爲了接收不一樣的數據類型而對應的,只有一個特殊的MappedByteBuffer,本次先不學習它,後續再去了解它。
咱們主要以理解上面介紹的概念爲目的實現一個簡單的NIO編程,讀取文件夾內的文件,而後輸出到控制檯。
public static void testNio(){
try {
RandomAccessFile rdf=new RandomAccessFile("E:\\nio\\niotest.txt","rw");
//利用channel中的FileChannel來實現文件的讀取
FileChannel inChannel= rdf.getChannel();
//設置緩衝區容量爲10
ByteBuffer buf= ByteBuffer.allocate(10);
//從通道中讀取數據到緩衝區,返回讀取的字節數量
int byteRead=inChannel.read(buf);
//數量爲-1表示讀取完畢。
while (byteRead!=-1){
//切換模式爲讀模式,其實就是把postion位置設置爲0,能夠從0開始讀取
buf.flip();
//若是緩衝區還有數據
while (buf.hasRemaining()){
//輸出一個字符
System.out.print((char) buf.get());
}
//數據讀完後清空緩衝區
buf.clear();
//繼續把通道內剩餘數據寫入緩衝區
byteRead = inChannel.read(buf);
}
//關閉通道
rdf.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
複製代碼
我在磁盤中niotest.txt的內容是hello world,咱們看看運行結果是否是hello world。
結果和預期同樣,咱們完成了NIO編程輸出磁盤文件內容,其實上面代碼中,我第一印象有疑問的地方就是buf.flip()
,其餘只要用過IO的應該都能理解,既然不能理解咱們就先調試下,註釋掉該段內容,看看輸出結果如何。
註釋掉buf.flip()
後,輸出結果果然不對了,那到底是爲啥呢?
buf.hasRemaining()
爲false,因此buffer第一次沒有輸出任何東西。看看第二次循環
其實這整個循環能夠解析步驟以下:
buffer讀取了10字節內容,內容就是:hello worl。
buf.hasRemaining() 判斷爲false,直接清空buffer(直接把position復位爲0,能夠直接覆蓋內容),讀取剩下內容。
最後只剩下一個字符 d
讀取,這個時候讀取完後,buffer內容以下:dello worl。
最後輸出由於從postion=1位置輸出,因此輸出:ello worl。
根據以上解析,咱們發現註釋了buf.flip()後,position位置寫入是什麼位置,讀出就是什麼位置,因此,該方法應該就是把position賦值爲0,從開始讀取。解讀源碼也證明了個人猜測,源碼以下:
public final Buffer flip() {
limit = position;
position = 0;
mark = -1;
return this;
}
複製代碼
《JAVA NIO》