8 Java NIO FileChannel-翻譯

王金龍發表於2017-12-06

Java NIO FileChannel是一個連線檔案的Channel。通過file channel,可以從檔案中讀取資料,也可以寫入資料到檔案。Java NIO的FileChannel是Java 標準IO的替代方案。

FileChannel不能設定為非阻塞模式,它一直執行在阻塞模式。

Opening a FileChannel

在使用FileChannel之前需要先開啟它。FileChannel不能直接開啟它。獲得FileChannel必須通過InputStream,OutputStrerm,RandomAccessFile。下面是一個通過RandomAccessFile開啟FileChannel的例子。

RandomAccessFile file = new RandomAccessFile("data/nio.txt","rw");
FileChannel fileChannel = file.getChannel();
複製程式碼

Reading Data from a FileChannel

可以通過read()方法從FileChannel讀取資料。下面是一個例子。

ByteBuffer buf = ByteBuffer.allocate(48);
int byteRead = inChannel.read(buf);
複製程式碼

首先,為一個Buffer分配空間,從FileChannel中讀取的資料將放入到Buffer中。

然後,呼叫FileChannel的read方法。這個方法將FileChannel中的資料儲存到Buffer中。read()方法的返回值表明向Buffer寫入的位元組數。如果返回-1,表明資料已經讀完。

Writing Data to a FileChannel

向FileChannel中寫入資料是通過FileChannel.write()方法來實現的,這個方法傳遞一個buffer引數。下面是一個例子。

String newData = "New String to write to a 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中已經沒有尚未寫入通道的位元組。

Closing a FileChannel

當FileChannel使用完之後需要關閉。下面是一個例子。

channel.close();
複製程式碼

FileChannel Position

在向FileChannel中讀寫資料時需要在一個指定的位置進行。可以通過FileChannel的position()方法來獲得當前位置。

也可以通過FileChannel的position(long pos)方法來設定當前位置。

這裡是兩個例子。

long pos = channel.position();
channel.position(pos+123);
複製程式碼

如果將position設定在檔案結束符之後,並且嘗試從通道中讀取資料,方法將會返回-1。檔案結束標記。

如果將position設定在檔案結束符之後,並且嘗試從通道中寫入資料,檔案將撐大到當前位置,並且寫入資料。這將導致檔案空洞,磁碟上物理檔案寫入的資料間將會有空隙。

FileChannel Size

FileChannel的size()方法返回的是通道所連線的檔案的大小。下面是一個例子。

long fileSize = channel.size();
複製程式碼

FileChannel Truncate

可以通過FileChannel的truncate方法擷取一個檔案。當擷取一個檔案時,檔案在給定長度後面的內容都會被刪除。例子如下:

channel.truncate(1024);
複製程式碼

這個例子將檔案截斷到1024個位元組。

FileChannel Force

FileChannel的force()會強制將未寫入到磁碟的資料儲存到磁碟。作業系統出於效能考慮可能會快取資料在記憶體中。所以並不能夠保證寫入到Channel中的資料真正寫入到磁碟上,除非呼叫了force()方法。

force()方法有一個布林值引數,表示檔案的後設資料是否也需要被重新整理。

下面是一個同時重新整理資料和後設資料的一個例子。

channel.force(true);
複製程式碼

相關文章