1. 程式人生 > >NIO 學習(三) channel(主要介紹channel----FileChannel詳解--通道間的資訊傳輸)

NIO 學習(三) channel(主要介紹channel----FileChannel詳解--通道間的資訊傳輸)

Channel實現

Java NIO中最重要的通道的實現:

FileChannel :從檔案中讀寫資料

DatagramChannel :通過UDP讀寫網路中的資料

SocketChannel  :通過TCP讀寫網路中的資料

ServerSocketChannel :監聽TCP連線,對每一個新進來的連線都會建立一個ScoketChannel

FileChannel

FileChannel 檔案通道,通過通道讀寫檔案,無法設定為非阻塞模式

開啟FileChannel

在使用FileChannel之前,必須先開啟它,需要通過使用inputStream,outputStream或者RandomAccessFile來獲取例項

File file = new File("C:\\Users\\Administrator\\Desktop\\editChargeInfo.jsp");
FileChannel fileChannel = new RandomAccessFile(file, "rw").getChannel();

從FileChannel中讀取資料

FileChannel -> buffer ,呼叫通道的read方法,底層會呼叫緩衝區的put方法

//從fileChannel中讀取資料
ByteBuffer buffer = ByteBuffer.allocate((int)file.length());
buffer.clear();
int read = fileChannel.read(buffer);

首先,建立一個buffer,從FileChannel中讀取到的資料,將讀到buffer緩衝區中,返回的數值,表示讀取到緩衝區的位元組數,如果返回-1,表示到了檔案末尾

向FileChannel中寫資料

FileChannnel <- buffer,呼叫通道的write方法,底層呼叫緩衝區的get方法

//向FileChannel中寫資料
String data = "It is a FileChannel,now write some data to Channnel at its end";
byte[] b = data.getBytes();
buffer.clear();
buffer.put(b);
buffer.flip();
while(buffer.hasRemaining()){
	fileChannel.write(buffer);
}

關閉FileChannel

使用完FileChannel後,必須將它關閉,呼叫close方法

FileChannel的其他方法

position()/position(long pos)方法

使用position()方法獲取FileChannel的當前位置,呼叫position(long pos) 方法設定FileChannel的當前位置

long position = fileChannel.position();
fileChannel.position(position+123);//設定FileChannel的位置

如果將位置設定的檔案結束符之後,然後試圖從檔案通道中讀取資料,讀方法將返回-1,檔案結束標識

如果將位置設定在檔案結束之後,然後向通道中寫資料,檔案將撐大當前位置並寫入資料,可能導致檔案空洞,磁碟上物理檔案中寫入的資料間有空隙

size()方法

返回檔案通道關聯檔案的位元組數

truncate(long size)

擷取檔案的長度,擷取的是檔案的前多上位元組的長度內容

force(Boolean b)

force將通道內未寫入到磁碟的資料強制寫入到磁碟上。

出於效能方面的考慮,作業系統會將資料快取在記憶體中,所以無法保證寫入到FileChannel裡的資料一定會即時寫到磁碟上。要保證這一點,需要呼叫force()方法。

force()方法有一個boolean型別的引數,指明是否同時將檔案元資料(許可權資訊等)寫到磁碟上。

通道間的資料傳輸

java NIO中兩個通道中如果有一個是FileChannel,就可以將資料從一個Channel傳輸到另一個Channel

transferFrom()

destTarge.transferFrom( src, position, count)

destTarge: FileChannel

src:channel

position:開始位置

count:傳輸的總位元組數

FileChannel的transferFrom()方法可以將資料從源通道就是方法中的通道資料傳輸到FileChannel中

File file = new File("C:\\Users\\Administrator\\Desktop\\editChargeInfo.jsp");
srcChannel = new RandomAccessFile(file, "rw").getChannel();
File filet = new File("C:\\Users\\Administrator\\Desktop\\t.jsp");
targetChannel = new RandomAccessFile(filet, "rw").getChannel();
targetChannel.transferFrom(srcChannel, 0, srcChannel.size());
targetChannel.force(false);
注意到:

如果src是socketchannel,只會傳輸準備好的位元組,不一定傳輸count個位元組

transferTo()

FileChannel.transferTo(int position,int count, Channel target)

從檔案通道FileChannel傳輸資料到Channel中,兩者有點類似,只不過反過來而已

如果target是socketchannel,一直傳輸資料直到buffer填滿

srcChannel = new RandomAccessFile(file, "rw").getChannel();
File filet = new File("C:\\Users\\Administrator\\Desktop\\test.jsp");
targetChannel = new RandomAccessFile(filet, "rw").getChannel();
srcChannel.transferTo(0, srcChannel.size(), targetChannel);
targetChannel.force(false);

可以使用fileChannel優化大檔案的複製工作,效率很高