六、Nio之FileChannel
Java NIO 中的 FileChannel 是一個連線到檔案的通道。可以通過檔案通道讀寫檔案。
FileChannel 無法設定為非阻塞模式,它總是執行在阻塞模式下。
開啟 FileChannel:
在使用FileChannel之前, 必須先開啟它。 但是, 我們無法直接開啟一個FileChannel, 需要通過使用一個InputStream、
OutputStream 或 RandomAccessFile 來獲取一個 FileChannel 例項。下面是通過 RandomAccessFile 開啟
FileChannel 的示例:
RandomAccessFile aFile = new RandomAccessFile("data/nio-data.txt", "rw");
FileChannel inChannel = aFile.getChannel();
從 FileChannel 讀取資料:
呼叫多個 read()方法之一從 FileChannel 中讀取資料。如:
ByteBuffer buf = ByteBuffer.allocate(48);
int bytesRead = inChannel.read(buf);
首先,分配一個 Buffer。從 FileChannel 中讀取的資料將被讀到 Buffer 中。
然後,呼叫 FileChannel.read()方法。該方法將資料從 FileChannel 讀取到 Buffer 中。read()方法返回的 int 值表示了有多少位元組被讀到了 Buffer 中。如果返回-1,表示到了檔案末尾。
向 FileChannel 寫資料:
使用 FileChannel.write()方法向 FileChannel 寫資料,該方法的引數是一個 Buffer。如:
String newData = "New String to write to file..." + System.currentTimeMillis();
ByteBuffer buf = ByteBuffer.allocate(48);
buf.clear();
buf.put(newData.getBytes());
buf.flip();
while(buf.hasRemaining()) {
channel.write(buf);
}
注意 FileChannel.write()是在 while 迴圈中呼叫的。因為無法保證 write()方法一次能向 FileChannel 寫入多少位元組,因此需要重複呼叫 write()方法,直到 Buffer 中已經沒有尚未寫入通道的位元組。
關閉 FileChannel:
用完 FileChannel 後必須將其關閉。如:
channel.close();
FileChannel 的 的 position 方法:
有時可能需要在 FileChannel 的某個特定位置進行資料的讀/寫操作。
可以通過呼叫 position()方法獲取 FileChannel的當前位置。
也可以通過呼叫 position(long pos)方法設定 FileChannel 的當前位置。
這裡有兩個例子:
long pos = channel.position();
channel.position(pos +123);
如果將位置設定在檔案結束符之後,然後試圖從檔案通道中讀取資料,讀方法將返回-1 —— 檔案結束標誌。
如果將位置設定在檔案結束符之後,然後向通道中寫資料,檔案將撐大到當前位置並寫入資料。這可能導致“檔案空
洞”,磁碟上物理檔案中寫入的資料間有空隙。
FileChannel 的 的 size 方法:
FileChannel 例項的 size()方法將返回該例項所關聯檔案的大小。如:
long fileSize = channel.size();
FileChannel 的 的 truncate 方法:
可以使用 FileChannel.truncate()方法擷取一個檔案。擷取檔案時,檔案將中指定長度後面的部分將被刪除。如:
channel.truncate(1024);
這個例子擷取檔案的前 1024 個位元組。
FileChannel 的 的 force 方法:
FileChannel.force()方法將通道里尚未寫入磁碟的資料強制寫到磁碟上。出於效能方面的考慮,作業系統會將資料
快取在記憶體中, 所以無法保證寫入到 FileChannel 裡的資料一定會即時寫到磁碟上。 要保證這一點, 需要呼叫 force()
方法。
force()方法有一個 boolean 型別的引數,指明是否同時將檔案元資料(許可權資訊等)寫到磁碟上。
下面的例子同時將檔案資料和元資料強制寫到磁碟上:
channel.force(true);