java核心學習(十八) javaNIO框架---“塊”模型的IO
一、java新IO概述
javaIO中的輸入流和輸出流都是通過字節的移動來處理的,面向流的輸入輸出系統一次只能處理一個字節,因此效率不高,而且傳統的輸入輸出流是阻塞試的,也就是說當無法讀到數據時,當前線程會被阻塞直到讀取到有效數據才會繼續運行。
java1.4之後提供了一系列改進的輸入輸出類與方法,並且以NIO為基礎改寫了java.io包中的類,新增了滿足NIO的功能。
NIO采用內存映射文件的方式,java.nio中主要的包有:
java.nio ,主要包含於Buffer相關的類;
java.nio.charset,主要包含字符集相關的類;
java.nio.channels,主要包含Channel和Selector相關的類;
java.nio.channels.spi,主要包含與Channel相關的服務提供者編程接口;
java.nio.charset.spi,包含與字符集相關的服務提供者編程接口。
二、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的工作方式不在這裏深究= =,因為深究了沒有實際應用也會忘記。。
三、 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(); } } }
四、Charset類
字符集類主要用於文本格式數據編碼與解碼,具體用法在 三 中的第一個例子有所展示。
java核心學習(十八) javaNIO框架---“塊”模型的IO