Channels和Buffers是JAVA NIO裡面比較重要的兩個概念,NIO正是基於Channels和Buffers進行數據操作,且數據總是從Channels讀取到Buffers,或者從Buffers寫入到Channels。
以FileChannel為例,如下:
FileChannel是文件寫入/讀取相關的通道;
產生FileChannel的方式:
下面舉個例子,分別從FileOutputStream、RandomAccessFile、FileInputStream中獲取文件通道,進行相關寫入/讀取操作;
package com.pichen.io;
import java.nio.*;
import java.nio.channels.*;
import java.io.*;
public class GetChannel {
private static final int BSIZE = 1024;
public static void main(String[] args) throws Exception {
// 創建文件輸出字節流
FileOutputStream fos = new FileOutputStream("data.txt");
//得到文件通道
FileChannel fc = fos.getChannel();
//往通道寫入ByteBuffer
fc.write(ByteBuffer.wrap("Some text ".getBytes()));
//關閉流
fos.close();
//隨機訪問文件
RandomAccessFile raf = new RandomAccessFile("data.txt", "rw");
//得到文件通道
fc = raf.getChannel();
//設置通道的文件位置 為末尾
fc.position(fc.size());
//往通道寫入ByteBuffer
fc.write(ByteBuffer.wrap("Some more".getBytes()));
//關閉
raf.close();
//創建文件輸入流
FileInputStream fs = new FileInputStream("data.txt");
//得到文件通道
fc = fs.getChannel();
//分配ByteBuffer空間大小
ByteBuffer buff = ByteBuffer.allocate(BSIZE);
//從通道中讀取ByteBuffer
fc.read(buff);
//調用此方法為一系列通道寫入或相對獲取 操作做好准備
buff.flip();
//從ByteBuffer從依次讀取字節並打印
while (buff.hasRemaining()){
System.out.print((char) buff.get());
}
fs.close();
}
}
再舉個文件復制的例子,有兩種方式:
如下代碼示例:
package com.pichen.io;
import java.nio.*;
import java.nio.channels.*;
import java.io.*;
public class ChannelCopy {
private static final int BSIZE = 1024;
public static void main(String[] args) throws Exception {
//獲取文件輸入輸出字節流
FileInputStream fis = new FileInputStream("C:\\test.jpg");
FileOutputStream fos = new FileOutputStream("C:\\test_copy.jpg");
//從文件輸入輸出字節流中獲取通道
FileChannel fci = fis.getChannel();
FileChannel fco = fos.getChannel();
//分配ByteBuffer空間大小
ByteBuffer buffer = ByteBuffer.allocate(BSIZE);
//第一種種數據拷貝方式,直接往輸入通道寫數據
while (fci.read(buffer) != -1) {
//為寫入操作做准備
buffer.flip();
//往輸出通道寫入buffer
fco.write(buffer);
//清空buffer,重置內部指針
buffer.clear();
}
//第二種數據拷貝方式,利用transferTo或者transferFrom方式
FileOutputStream fos2 = new FileOutputStream("C:\\test_copy2.jpg");
FileChannel fco2 = fos.getChannel();
fci.transferTo(0, fci.size(), fco2);
fis.close();
fos.close();
fos2.close();
}
}
buffer用於與通道進行交互,舉個例子如下,這裡以ByteBuffer為例;
package com.pichen.io;
import java.nio.*;
import java.nio.channels.*;
import java.io.*;
public class GetChannel {
private static final int BSIZE = 1024;
public static void main(String[] args) throws Exception {
// 隨機訪問文件
RandomAccessFile raf = new RandomAccessFile("C:\\data.txt", "rw");
// 得到文件通道
FileChannel fc = raf.getChannel();
ByteBuffer bf = ByteBuffer.allocate(BSIZE);
int bytesRead = fc.read(bf); // read into buffer.
while (bytesRead != -1) {
// 通過flip()方法將Buffer從寫模式切換到讀模式
bf.flip();
while (bf.hasRemaining()) {
// 每次讀取一個字節
System.out.print((char) bf.get());
}
// 清空緩存,准備往緩存寫數據
bf.clear();
bytesRead = fc.read(bf);
}
// 關閉
raf.close();
}
}
compact:往buffer寫數據之前調用,只清除已讀取的數據,新寫入的數據會添加到未讀數據末尾;(Buffer buffer)方法,調用Buffer的put方法write(Buffer buffer)方法調用Buffer的get方法
參考:http://ifeve.com/java-nio-all/