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優化大檔案的複製工作,效率很高