java核心學習(十八) javaNIO框架---「塊」模型的IO

1、java新IO概述java

  javaIO中的輸入流和輸出流都是經過字節的移動來處理的,面向流的輸入輸出系統一次只能處理一個字節,所以效率不高,並且傳統的輸入輸出流是阻塞試的,也就是說當沒法讀到數據時,當前線程會被阻塞直到讀取到有效數據纔會繼續運行。編程

  java1.4以後提供了一系列改進的輸入輸出類與方法,而且以NIO爲基礎改寫了java.io包中的類,新增了知足NIO的功能。網絡

  NIO採用內存映射文件的方式,java.nio中主要的包有:app

    java.nio ,主要包含於Buffer相關的類;dom

    java.nio.charset,主要包含字符集相關的類;編碼

    java.nio.channels,主要包含Channel和Selector相關的類;spa

    java.nio.channels.spi,主要包含與Channel相關的服務提供者編程接口;線程

    java.nio.charset.spi,包含與字符集相關的服務提供者編程接口。code

2、Buffer抽象類對象

  其子類有ByteBuffer(最經常使用)、CharBuffer、ShortBuffer、IntBuffer、LongBuffer、FloatBuffer、DoubleBuffer,這些類沒有構造器,獲取buffer對象使用以下靜態方法:static XxxBuffer allocate(int capacity)。

  Buffer的幾個位置屬性:

  

  相應的兩個方法:clear(),let limit = capacity and position = 0,這至關因而爲再次將數據寫入Buffer作好準備,

          flip(),let limit = position and position = 0 ,這至關因而爲從Buffer中取出數據作好準備。

package NIOTest;

import java.nio.CharBuffer;

public class BufferTest {
    public static void main(String[] args)
    {
        CharBuffer buffer = CharBuffer.allocate(8);
        System.out.println("capacity:" +buffer.capacity());
        System.out.println("limit:" +buffer.limit());
        System.out.println("position" + buffer.position());

        buffer.put('a');
        buffer.put('b');
        buffer.put('c');
        System.out.println("加入三個元素後,position = " + buffer.position());
        buffer.flip();
        System.out.println("執行flip()後,limit = " + buffer.limit());
        System.out.println("position = " + buffer.position());
        //去除第一個元素
        System.out.println("第一個元素(position=0):" + buffer.get());
        System.out.println("取出第一個元素後,position = " + buffer.position());
        //調用clear方法
        buffer.clear();
        System.out.println("執行clear()後,limit = " + buffer.limit());
        System.out.println("執行clear()後,position = " + buffer.position());
        System.out.println("執行clear()後,buffer內容並無被清除:" + "第三個元素爲:"+ buffer.get(2));
        System.out.println("執行絕對讀取後,position = " + buffer.position());
    }
}

  上面代碼嘗試了一下Buffer的使用,輸出爲下

capacity:8
limit:8
position0
加入三個元素後,position = 3
執行flip()後,limit = 3
position = 0
第一個元素(position=0):a
取出第一個元素後,position = 1
執行clear()後,limit = 8
執行clear()後,position = 0
執行clear()後,buffer內容並無被清除:第三個元素爲:c
執行絕對讀取後,position = 0

  上面程序使用的buffer是heapbuffer,每一個heapbuffer在新建時都會建立一個對應的directbuffer,直接buffer的讀取效率高可是建立成本也高,具體buffer1的工做方式不在這裏深究= =,由於深究了沒有實際應用也會忘記。。

 

3、 Channel接口

  Channel用於與Buffer交互,實現數據的IO。

  java爲Channel接口提供了DatagramChannel(支持UDP網絡通訊)、FileChannel(文件讀寫)、Pipe.SinkChannel和Pipe.SourceChannel(支持線程間通訊的管道)、SelectableChannel(可選擇阻塞與非阻塞的channel)、ServerSocketChannel和SocketChannel(支持TCP網絡通訊)等等。

  Channel經過傳統的流節點來返回對應的Channel,經常使用的方法有map()、read()、write(),下面來試一試

  

package NIOTest;


import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.CharBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;

public class FileChannelTest {
    public static void main(String[] args) {
        File f = new File("./src/main/java/NIOTest/FileChannelTest.java");
        try (
                FileChannel inChannnel = new FileInputStream(f).getChannel();
                FileChannel outChannel = new FileOutputStream("a.txt").getChannel();

        ) {
            MappedByteBuffer buffer = inChannnel.map(FileChannel.MapMode.READ_ONLY, 0, f.length());
            Charset charset = Charset.forName("GBK");
            outChannel.write(buffer);
            buffer.clear();
            CharsetDecoder decoder = charset.newDecoder();
            CharBuffer charBuffer = decoder.decode(buffer);
            System.out.println(charBuffer);


        } catch (IOException ioe) {
            ioe.printStackTrace();
        }
    }
}

  下面代碼每次運行都會講a.txt文件的內容複製一份並將所有內容追加到該文件的後面

package NIOTest;

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;

public class RandomFileChannelTest {
    public static  void mian (String[] args){
        File f= new File("a.txt");
        try(
                RandomAccessFile raf = new RandomAccessFile(f,"rw");
                FileChannel randomChannel = raf.getChannel();
                ){
            ByteBuffer buffer = randomChannel.map(FileChannel.MapMode.READ_ONLY,0,f.length());
       //這裏移動的是channel的position,能夠在任意位置將數據寫入channel。 randomChannel.position(f.length()); randomChannel.write(buffer); }
catch (IOException ioe){ ioe.printStackTrace(); } } }

 

4、Charset類

  字符集類主要用於文本格式數據編碼與解碼,具體用法在 三 中的第一個例子有所展現。

相關文章
相關標籤/搜索