java讀寫檔案時nio、bio對比
IO 是主存和外部裝置 ( 硬碟、終端和網路等 ) 拷貝資料的過程。 IO 是作業系統的底層功能實現,底層通過 I/O 指令進行完成。所有語言執行時系統提供執行 I/O 較高級別的工具。 (c 的 printf scanf,java 的面向物件封裝 )
2. Java 標準 io 回顧
Java 標準 IO 類庫是 io 面向物件的一種抽象。基於本地方法的底層實現,我們無須關注底層實現。 InputStream\OutputStream( 位元組流 ) :一次傳送一個位元組。 Reader\Writer( 字元流 ) :一次一個字元。
3. nio 簡介
nio是java New IO的簡稱,在jdk1.4裡提供的新api。Sun官方標榜的特性如下:
– 為所有的原始型別提供 (Buffer) 快取支援。
– 字符集編碼解碼解決方案。
– Channel :一個新的原始 I/O 抽象。
– 支援鎖和記憶體對映檔案的檔案訪問介面。
– 提供多路 (non-bloking) 非阻塞式的高伸縮性網路 I/O 。
本文將圍繞這幾個特性進行學習和介紹。
4. Buffer&Chanel
Channel和buffer是NIO是兩個最基本的資料型別抽象。
Buffer:
– 是一塊連續的記憶體塊。
– 是 NIO 資料讀或寫的中轉地。
Channel:
– 資料的源頭或者資料的目的地
– 用於向 buffer 提供資料或者讀取 buffer 資料 ,buffer 物件的唯一介面。
– 非同步 I/O 支援
java原來的I/O體系中, I/O實際上是以Stream(流)這個抽象概念被使用,所有的I/O實際上被看做是單個位元組一個位元組一個位元組的移動; Stream I/O被用來和外界世界互動,在內部它用來將物件轉為bytes位元組流,然後再轉為物件;
NIO的角色和目標實際上和原來的I/O是相同的,但是它使用了一個不同的抽象概念:block I/O. 正如你將所見到的那樣,block I/O比原來的I/O有效率得多;
Streams和blocks的對比
原來的I/O包和NIO處理資料最大的不同之處在於資料打包(packaged)和傳輸(transmitted)的方式。正如前面所提到的那樣,IO(java.io.*)是以流的方式處理資料的,而NIO是以blocks(塊)的方式來處理資料的.
一個流面向(stream-oriented)的I/O系統在處理資料時是一次只處理一個位元組;作為input的stream一次向計算機生產一個byte,作為output的stream一次向計算機要求消費一個byte(計算機生產byte),對stream建立filter是一件非常容易的事情,同時如果你希望通過chain模式將幾個filter連在一起也很容易,最終可以將大量複雜的處理分成一個簡單,巧妙的處理模式;但是同時,stream-oriented的I/O處理通常非常低效率。
而一個塊面向(block-oriented)的I/O系統成塊的處理資料,每次操作都會生產或者消費以block為單位的資料;所以,這種方式會比stream-oriented的處理方式高效地多,但是block-oriented的I/O也缺少以stream-oriented程式設計時的簡單和優雅;
什麼是buffer?:
當資料寫入或者資料讀取時,這些資料被儲存在一個buffer物件中;buffer物件是nio和原io包中一個最重要的區別。在原來的io系統中,資料的讀取和獲得是首先通過Stream流物件。
在nio中,所有的資料採用buffers的方式進行處理。當資料被讀取的時候,讀入資料被先儲存到buffer中;資料寫入的時候,寫入資料也首先放置到buffer中。
一個buffer物件實際上是一個array物件,但是又不單單隻具有array的功能;一個buffer物件提供了結構化訪問資料的能力,並且記錄了系統讀/寫操作的日誌。
buffer的型別?:
最常見的使用buffer的方式是ByteBuffer,一個ByteBuffer的底層陣列允許get/set buffers的操作;
其他的buffer型別包括:CharBuffer,ShotBuffer,
IntBuffer, LongBuffer, DoubleBuffer,FloatBuffer;
每一種buffer的型別都是一個buffer介面;這些介面的行為除了處理的資料不同之外, 操作行為非常相似; 不過因為ByteBuffer被用來和大多數標準的I/O操作,所以除了共有的buffer操作之外,還有一些特別的操作行為;
什麼是channel?:
一個Channel是一個可以操作讀寫資料的物件,channel的概念類似於io包中的stream(流)概念;
如前所述,在nio中,所有的資料是通過buffer這個物件進行處理的;在讀寫資料的時候,你永遠不需要直接地操作Channel物件;
channel的型別?:
和io中流(Stream)概念不同的是,channel是雙向的;一個流必須是InputStream或者OutputStream的子類,一個Channel可以是讀/寫操作的任何一種或兩種;因為channel的雙向特性,和流比起來更真實地反映了os的底層,尤其在Unix中。