NIO中兩個核心對象爲Channel(通道)和Buffer(緩衝)
Buffer,ByteBuffer,CharBuffer,DoubleBuffer,FloatBuffer,IntBuffer,LongBuffer,ShortBuffer,MappedByteBuffer(ByteBuffer的子類)
實例化Buffer的方法(MappedByteBuffer除外):
ByteBuffer bb = ByteBuffer.allocate(capacity);
capacity爲緩衝區容量。
對Buffer屬性的一系列操作:
public static void BufferTest() {
//創建普通的buffer
ByteBuffer bb = ByteBuffer.allocate(8);
//創建直接buffer和普通buffer對比是創建成本高,I/O操作較快
ByteBuffer bb2 = ByteBuffer.allocateDirect(8);
//buffer的三屬性 關係爲 容量cap>=界限lim>=位置pos
//容量
bb.capacity();
//界限
bb.limit();
//位置
bb.position();
/*
* 向普通buffer中存入元素,position隨添加的元素而增漲初始爲0
* pos=0 lim=8 cap=8
*/
bb.put((byte) 'a');
bb.put((byte) 'b');
/*
* pos=2 lim=8 cap=8
* buffer爲非空調用flip()爲輸出做準備
* 執行flip()後 limit指到有效長度position指到0的位置
*/
bb.flip();
/*
* pos=0 lim=2 cap=8
* 輸出數據結束後調用clear()爲下次輸入做準備
* 執行clear()後 limit指到capacity位置position指到0位置
*/
bb.clear();
/*
* pos=0 lim=8 cap=8
* 如果再添加c元素到buffer 這時的position應該向後+1,並且覆蓋掉原來的a
*/
bb.put((byte) 'c');
//pos=1 lim=8 cap=8
}
Channel類
通過下面這個方法來了解:
/**
* 傳統的IO效率不高因爲是依賴與字節來處理
* nio是依賴於映射內存區塊來處理處理效率高
* 該方法典型的就是oc.write(mbbuffer);
* mbbuffer是Struts2Test.java的緩衝區塊,這裏是直接整塊寫出
* 傳統的一般會類似:
* String str = "";
* while(str = buffer.readLine() != null) {
* xxx.write(str);
* }
*/
public static void channelTest() throws IOException {
/*
* Channel的實現類有:
* java.nio.channels包下
* DatagramChannel,FileChannel,SelectableChannel
* ServerSocketChannel,SocketChannel(支持tcp網絡通信的管道)
* java.nio.channels.Pipe包下
* SinkChannel,SourceChannel(線程之間的通信管道)
*/
//創建Channel實例 一般通過節點流創建Channel
File fileIn = new File("F:"+File.separator+"testSource"+File.separator+"Struts2Test.java");
File fileOut = new File("F:"+File.separator+"testSource"+File.separator+"nioTest.txt");
//創建節點流
FileInputStream fis = new FileInputStream(fileIn);
FileOutputStream fos = new FileOutputStream(fileOut);
//創建Channel
FileChannel ic = fis.getChannel();
FileChannel oc = fos.getChannel();
//Channel常用三方法map write read
//通過map方法把Channel包裝成Buffer
MappedByteBuffer mbbuffer = ic.map(MapMode.READ_ONLY, 0, fileIn.length());
//Channel只能與buffer交互不能直接訪問Channel的數據
oc.write(mbbuffer);
mbbuffer.clear();
ic.close();
oc.close();
}
Channel的read類似write操作
如果在noiTest.txt文件末尾追加Struts2Test.java的內容,可以在上面代碼中
26行改爲
//追加到文件末尾
FileOutputStream fos = new FileOutputStream(fileOut, true);
32、33行之間加入
oc.position(fileOut.length());
結合Buffer的position屬性不難推知這句代碼的含義
編碼解碼就是ByteBuffer和CharBuffer之間的轉換
Char轉Byte爲編碼 反之爲解碼
下面代碼簡單說明了編碼和解碼:
public static void main(String[] args) throws CharacterCodingException {
//Encode編碼(Char->Byte) Decode解碼(Byte->Char)
//獲取Charset
Charset cs = Charset.forName("GBK");
//實例化普通Buffer
CharBuffer cb =CharBuffer.allocate(8);
cb.put("牛");
cb.put("羊");
cb.put("馬");
cb.flip();
//Charset自帶編碼
ByteBuffer bb = cs.encode(cb);
for(int i=0;i<bb.capacity();i++) {
System.out.println(bb.get(i)+"\t");
}
System.out.println();
//Charset自帶解碼
CharBuffer cbNext = cs.decode(bb);
System.out.println(cbNext);
//編碼 nio
CharsetEncoder ce = cs.newEncoder();
ByteBuffer niobb = ce.encode(cbNext);
for(int i=0;i<niobb.capacity();i++) {
System.out.println(niobb.get(i)+"\t");
}
//解碼 nio
CharsetDecoder cd = cs.newDecoder();
CharBuffer niocb = cd.decode(niobb);
System.out.println(niocb);
}
}
上面代碼分別說明了兩種編碼和解碼