一、FileChannel的優勢
FileChannel是Java NIO庫中的一個重要類,作為Java中File I/O讀寫的另一種方式,相較於傳統的IO方式,FileChannel具有以下優勢:
1. 更快的I/O操作,只適用於間隔地讀或寫一個大容量的數據塊;
2. 可以直接操作直接內存映射文件,使用堆外內存讀寫操作;
3. 支持非阻塞I/O,可以使用單獨的線程讀寫文件,FileChannel中的data與NIO庫的selector結合可以實現同步非阻塞IO;
4. 支持多個並發訪問;
5. 可以鎖定文件的某個區域以進行獨佔訪問;
6. 可以將兩個或多個FileChannel中的數據直接傳輸,實現零拷貝,加快文件的讀取和寫入速度。
二、FileChannel讀取文件
FileChannel的read()方法提供了多種方式讀取文件。最常用的是使用ByteBuffer緩衝區進行讀取:
try(RandomAccessFile file = new RandomAccessFile("test.txt", "rw");
FileChannel channel = file.getChannel()){
ByteBuffer buffer = ByteBuffer.allocate(1024);
while (channel.read(buffer) != -1){
buffer.flip();
while (buffer.hasRemaining()){
System.out.print((char) buffer.get());
}
buffer.clear();
}
} catch (IOException e) {
e.printStackTrace();
}
三、FileChannel寫文件
FileChannel的write()方法提供了多種方式寫入數據到文件。最常用的是使用ByteBuffer緩衝區進行寫入:
try(RandomAccessFile file = new RandomAccessFile("test.txt", "rw");
FileChannel channel = file.getChannel()){
ByteBuffer buffer = ByteBuffer.allocate(1024);
buffer.put("Test String".getBytes());
buffer.flip();
while (buffer.hasRemaining()){
channel.write(buffer);
}
} catch (IOException e) {
e.printStackTrace();
}
四、FileChannel寫入文件
FileChannel提供了map()方法將一個文件區域直接映射到內存中,讀寫操作直接在內存中進行:
try(RandomAccessFile file = new RandomAccessFile("test.txt", "rw");
FileChannel channel = file.getChannel()){
MappedByteBuffer buffer = channel.map(FileChannel.MapMode.READ_WRITE, 0, 1024);
buffer.put("Test String".getBytes());
} catch (IOException e) {
e.printStackTrace();
}
五、FileChannel線程安全
FileChannel是線程安全的,因為FileChannel實例方法中的狀態是由操作系統中的文件對象來維護的。即使有多個線程同時對同一個FileChannel操作,操作系統也會協作來保證正確的順序和正確的結果。
六、FileChannel可以實現數據零拷貝
FileChannel提供的transferTo()方法和transferFrom()方法可以非常高效地傳輸數據,實現數據的零拷貝。
try(RandomAccessFile file = new RandomAccessFile("src.txt", "rw");
FileChannel srcChannel = file.getChannel();
RandomAccessFile outputFile = new RandomAccessFile("dest.txt", "rw");
FileChannel outputChannel = outputFile.getChannel()
) {
long position = 0;
long count = srcChannel.size();
srcChannel.transferTo(position, count, outputChannel);
} catch (IOException e) {
e.printStackTrace();
}
七、FileChannel.write的寫入速度
FileChannel通過ByteBuffer進行寫入操作的性能非常高,一般會比傳統的IO方式的性能快很多。下面我們來比較一下FileChannel和傳統的IO流的寫入速度:
try(FileOutputStream fos = new FileOutputStream("test.txt")){
FileChannel fileChannel = fos.getChannel();
long start = System.currentTimeMillis();
for (int i = 0; i < 100000; i++) {
ByteBuffer buffer = ByteBuffer.allocate(64);
buffer.put("123456789012345678901234567890123456789012345678901234567890123\n".getBytes());
buffer.flip();
fileChannel.write(buffer);
}
System.out.println("FileChannel Time:" + (System.currentTimeMillis() - start) + " ms");
} catch (IOException e) {
e.printStackTrace();
}
try(FileOutputStream fos = new FileOutputStream("test.txt")){
long start = System.currentTimeMillis();
for (int i = 0; i < 100000; i++) {
fos.write("123456789012345678901234567890123456789012345678901234567890123\n".getBytes());
}
System.out.println("FileOutputStream Time:" + (System.currentTimeMillis() - start) + " ms");
} catch (IOException e) {
e.printStackTrace();
}
八、FileChannel.map
FileChannel提供的map方法可以將文件映射為一個ByteBuffer。通過修改ByteBuffer中的數據會修改文件的內容:
try(RandomAccessFile file = new RandomAccessFile("test.txt", "rw");
FileChannel channel = file.getChannel()){
MappedByteBuffer buffer = channel.map(FileChannel.MapMode.READ_WRITE, 0, channel.size());
buffer.put(0, (byte) 'H');
buffer.put(1, (byte) 'e');
buffer.put(2, (byte) 'l');
buffer.put(3, (byte) 'l');
buffer.put(4, (byte) 'o');
} catch (IOException e) {
e.printStackTrace();
}
九、FileChannel.transferTo
FileChannel提供的transferTo方法將數據從源通道傳輸到目標通道,實現了零拷貝,速度比傳統的IO流快很多:
try(RandomAccessFile file = new RandomAccessFile("src.txt", "rw");
FileChannel srcChannel = file.getChannel();
RandomAccessFile outputFile = new RandomAccessFile("dest.txt", "rw");
FileChannel outputChannel = outputFile.getChannel()
) {
long position = 0;
long count = srcChannel.size();
srcChannel.transferTo(position, count, outputChannel);
} catch (IOException e) {
e.printStackTrace();
}
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/243387.html
微信掃一掃
支付寶掃一掃