public interface Channel extends Closeable { public boolean isOpen(); public void close() throws IOException; }
其中只包含最基本的兩個方法,以下圖是從《Java NIO》截取的Channel繼承樹。java
Channel可分爲可讀和可寫,實現了對應的可讀可寫的Channel接口或者抽象Channel類,就能夠讀寫兼併。數組
FileChannel:用於讀取、寫入、映射和操做文件的通道。網絡
DatagramChannel:經過 UDP 讀寫網絡中的數據通道。dom
SocketChannel:經過 TCP 讀寫網絡中的數據。socket
ServerSocketChannel:能夠監聽新進來的 TCP 鏈接,對每個新進來的鏈接都會建立一個 SocketChannel。spa
以上Channel都實現或者繼承了相應的Channel讀寫接口或者讀寫抽象類,因此都是可讀寫的。可是由於FileChannel能夠根據FileInputStream或者FileOutputStream獲取,因此當根據以上類獲取的FileChennel進行讀或者寫的時候會拋出異常。code
1. FileChannel對象的獲取:對象
@Test public void test() throws IOException{ //1. 使用FileInputStream獲取FileChannel FileInputStream fis = new FileInputStream("d:\\1.txt"); FileChannel fChannel = fis.getChannel(); //2. 使用FileOutputStream獲取FileChannel FileInputStream ois = new FileInputStream("d:\\1.txt"); FileChannel fChannel1 = ois.getChannel(); //3, 使用RandomAccessFile對象獲取 RandomAccessFile raf = new RandomAccessFile("d:\\1.txt", "rw"); FileChannel fChannel2 = raf.getChannel(); //4. FileChannel的open方法打開 FileChannel fChannel3 = FileChannel.open(Paths.get("d:\\1.txt"), StandardOpenOption.READ,StandardOpenOption.WRITE); }
2. 其餘三個網絡Channel的獲取方式:blog
@Test public void test2() throws IOException{ SocketChannel socketChannel = SocketChannel.open(new InetSocketAddress("127.0.0.1", 9898)); ServerSocketChannel ssChannel = ServerSocketChannel.open(); DatagramChannel datagramChannel = DatagramChannel.open(); }
1. 從Channel中讀取數據到buffer繼承
public abstract int read(ByteBuffer dst) throws IOException;
public abstract long read(ByteBuffer[] dsts, int offset, int length)throws IOException;
public final long read(ByteBuffer[] dsts) throws IOException {
return read(dsts, 0, dsts.length);
}
2. 將buffer中的數據寫入Channel
public abstract int write(ByteBuffer src) throws IOException;
public abstract long write(ByteBuffer[] srcs, int offset, int length)throws IOException;
public final long write(ByteBuffer[] srcs) throws IOException {
return write(srcs, 0, srcs.length);
}
3. 以下一段文件讀寫的代碼
public void test3() { FileInputStream fis = null; FileChannel inputChannel = null; FileOutputStream fos = null; FileChannel outputChannel = null; try { fis = new FileInputStream("d:\\1.txt"); inputChannel = fis.getChannel(); fos = new FileOutputStream("d:\\1.bak.txt"); outputChannel = fos.getChannel(); ByteBuffer buf = ByteBuffer.allocate(1024); int len = -1; while ((len = inputChannel.read(buf)) != -1) { buf.flip(); outputChannel.write(buf); buf.clear(); } } catch (IOException e) { e.printStackTrace(); } finally { if (outputChannel != null) { try { outputChannel.close(); } catch (Exception e2) { } } if (outputChannel != null) { try { outputChannel.close(); } catch (Exception e2) { } } if (inputChannel != null) { try { inputChannel.close(); } catch (Exception e2) { } } if (fos != null) { try { fos.close(); } catch (Exception e2) { } } if (fis != null) { try { fis.close(); } catch (Exception e2) { } } } }
public void test4() throws IOException { FileInputStream fis = new FileInputStream("d:\\1.txt"); FileChannel inputChannel = fis.getChannel(); FileOutputStream fos = new FileOutputStream("d:\\1.bak.txt"); FileChannel outputChannel = fos.getChannel(); // 直接從通道中讀,在內存中分配空間,在物理內存中直接操做 // inputChannel.transferTo(0,inputChannel.size() , outputChannel); outputChannel.transferFrom(inputChannel, 0, inputChannel.size()); }
1. 分散是將一個Channel中的數據寫到多個順序的buffer中,通常是傳進一個buffer數組中,Channel中的數據依次寫入buffer數組中的buffer當中。
2. 彙集是將多個buffer中的數據寫入同一個buffer中,通常操做是一個buffer數組。
代碼以下:
@Test public void test5() throws IOException { FileInputStream fis = new FileInputStream("d:\\1.txt"); FileChannel inputChannel = fis.getChannel(); FileOutputStream fos = new FileOutputStream("d:\\1.bak.txt"); FileChannel outputChannel = fos.getChannel(); ByteBuffer buf1 = ByteBuffer.allocate(1024); ByteBuffer buf2 = ByteBuffer.allocate(64); ByteBuffer buf3 = ByteBuffer.allocate(32); ByteBuffer[] bufs = { buf1, buf2, buf3 }; while (inputChannel.read(bufs) != -1) { // 分散讀取(Scattering Reads) inputChannel.read(bufs); for (ByteBuffer buf : bufs) { buf.flip(); } // 彙集寫入(Gathering Writes) outputChannel.write(bufs); for (ByteBuffer buf : bufs) { buf.clear(); } } }
Channel暫時想到這麼多東西,後續有想到的再補充,開始寫博客歡迎批評指正。
參看資料: 《Java NIO 中文版》