Java NIO FileChannel 是和文件連接的通道蔑歌。使用文件通道能夠在文件中讀寫數(shù)據(jù)。Java NIO FileChannel類是用來替代Java IO API標(biāo)準(zhǔn)文件讀寫的。
FileChannel不能被設(shè)置為費阻塞模式堕仔,它使用以阻塞模式運行躲因。
打開一個FileChannel
在使用FileChannel之前必須先打開它。不能直接打開FileChannel趁耗,需要通過InputStream沉唠,OutputStream或者RandomAccessFile獲得一個FileChannel。下面是一個用RandomAccessFIle獲得FileChannel的例子:
RandomAccessFile aFile = new RandomAccessFile("./data/nio-data.txt", "rw");
FileChannel inChannel = aFile.getChannel();
從FileChannel中讀取數(shù)據(jù)
調(diào)用read()方法從FileChannel中讀取數(shù)據(jù)苛败,例如:
ByteBuffer buf = ByteBuffer.allocate(48);
int bytesRead = inChannel.read(buf);
先分配一個Buffer满葛,數(shù)據(jù)從FileChannel讀到Buffer中径簿。
然后調(diào)用FileChannel.read()方法,這個方法把數(shù)據(jù)從FileChannel讀到Buffer中嘀韧。read()方法返回的int表示向Buffer中寫入了多少字節(jié)篇亭。如果返回-1,表明到達(dá)了文件的結(jié)尾锄贷。
往FileChannel中寫入數(shù)據(jù)
調(diào)用FileChannel.write()方法往文件中寫入數(shù)據(jù)暗赶。這需要一個Buffer作為參數(shù),例如:
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循環(huán)中調(diào)用肃叶。write()方法不保證有多少數(shù)據(jù)寫入FileChannel蹂随。因此我們需要重復(fù)調(diào)用write方法,直到Buffer中沒有byte需要寫入為止因惭。
關(guān)閉FileChannel
FileChannel用完之后必須關(guān)閉岳锁,例如:
channel.close();
FileChannel的Position
往FIleChannel中讀寫都是在特定位置進行。調(diào)用position()方法會獲得當(dāng)前的位置蹦魔。
通過position(long pos)能設(shè)置位置激率。
兩個例子:
long pos channel.position();
channel.position(pos + 123);
如果把位置設(shè)置到了文件末尾的后面,然后從文件中讀勿决,會得到-1——文件結(jié)尾的標(biāo)記乒躺。
如果把位置設(shè)置到了文件末尾的后面,然后往文件中寫低缩,文件將擴展到該位置然后寫入嘉冒,這樣會導(dǎo)致“文件空洞”,磁盤上物理文件寫入的數(shù)據(jù)間有間隙咆繁。
FileChannel的size
FileChannel的size()方法返回通道連接到的文件的大小讳推,例如:
long fileSize = channel.size();
FileChannel Truncate
調(diào)用FileChannel.truncate()方法能夠吧文件截取到指定長度。例如:
channel.truncate(1024);
例子將文件截取到1024字節(jié)玩般。
FileChannel Force
FileChannel.force()方法將通道中未寫入的數(shù)據(jù)寫到硬盤上银觅。處于性能考慮,操作系統(tǒng)可能將數(shù)據(jù)保存在緩存中坏为,所以不保證數(shù)據(jù)真的被寫到硬盤上了究驴,除非調(diào)用了force()方法。
force()方法以一個布爾值作為參數(shù)匀伏,指明是否將文件元數(shù)據(jù)(權(quán)限等)寫入洒忧。
下面是一個例子,往磁盤中寫數(shù)據(jù)和元數(shù)據(jù):
channel.force(true);