java新輸入/輸出(nio)記錄

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);
	}
}


上面代碼分別說明了兩種編碼和解碼

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章