筆者以前接觸的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的通道相似流,但又有些不一樣:服務器
既能夠從通道中讀取數據,又能夠寫數據到通道。但流的讀寫一般是單向的。 通道能夠異步地讀寫。網絡
通道中的數據老是要先讀到一個Buffer,或者老是要從一個Buffer中寫入。app
Channel的實現dom
這些是Java NIO中最重要的通道的實現:異步
FileChannel: 從文件中讀寫數據。socket
DatagramChannel : 能經過UDP讀寫網絡中的數據。post
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()
後,輸出結果果然不對了,那到底是爲啥呢?
上圖是第一個循環,咱們能夠看到緩衝區的position=10,limit=10,cap=10。調用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》