NIO详解
目錄
- NIO
- 前言
- IO與NIO的區別
- Buffer(緩沖區)
- Channel(通道)
- Charset(字符集)
- NIO遍歷文件
NIO
前言
NIO即New IO,這個庫是在JDK1.4中才引入的。NIO和IO有相同的作用和目的,但實現方式不同,NIO主要用到的是塊,所以NIO的效率要比IO高很多。在Java API中提供了兩套NIO,一套是針對標準輸入輸出NIO,另一套就是網絡編程NIO。
IO與NIO的區別
- IO流是面向流的,屬于阻塞IO,沒有選擇器。
- NIO流是面向塊(緩沖區),屬于非阻塞IO有選擇器。
其中最大的區別就是一個面向流,一個面向緩沖區。- 面向流:IO流每次讀取一個字節或者多個,直到讀完為止。不能對流中的數據進行操作。
- 面向緩沖區:NIO流是將數據放到一個緩沖區,需要時可以對緩沖區中的數據進行操作,這樣就可以更加靈活的操作數據了。(就好像IO流是一根水管,而NIO是一個運水車)
Buffer(緩沖區)
Buffer是一個抽象類;
子類有:ByteBuffer, CharBuffer, DoubleBuffer, FloatBuffer, IntBuffer, LongBuffer, ShortBuffer
核心類(常用類):ByteBuffer和CharBuffer 其中ByteBuffer有一個子類MappedByteBuffer(MappedByteBuffer類能夠將文件直接映射到內存中,那么這樣我們就可以像訪問內存一樣訪問文件,非常方便)
創建Buffer
因為Buffer都是抽象類,無法直接實例化。創建緩沖區要調用XxxBuffer allocate(int capacity),XxxBuffer allocateDirect(int capacity),參數是緩沖區容量。
eg:獲取ByteBuffer
static ByteBuffer allocate(int capacity)
分配一個新的字節緩沖區(普通Buffer)
static ByteBuffer allocateDirect(int capacity)
分配新的直接字節緩沖區(直接Buffer)
二者的區別:
Buffer參數
- capacity(容量):緩沖區的容量,不可以為負數,一旦創建了就不能夠改變
- limit(界限):是緩沖區讀寫數據的終止點,limit之后的區域無法訪問
- position(起始指針):是緩沖區讀寫數據的起始點,初始值為0。position隨著數據的加入而改變,例如讀取2個數據到Buffer中,則position = 2
- mark(標記):該索引能夠用于下次讀取或者寫入,mark在0~position之間,設置該值就會把position移動到mark處
Buffer方法
- flip():讀取模式;確定緩沖區數據的起始點和終止點,為輸出數據做準備(即寫入通道), 將limit的值改為postion的值,同時將postion歸0
- 特點: 就是為下一次數據的讀取做好準備
- clear():寫入模式;緩沖區初始化,準備再次接收新數據到緩沖區,將limit改為capacity的值,同時將postion歸0
- 特點: 就是為下一次數據的寫入做好準備
- get()和put():獲取元素和存放元素。使用clear()之后,無法直接使用get()獲取元素,需要使用get(int index)根據索引值來獲取相應元素
- hasRemaining():判斷postion到limit之間是否還有元素。
Channel(通道)
Channel原理類似于傳統的流對象,區別在于:
1.Channel能夠將指定的部分或者全部文件映射到內存中
2.程序如果想要讀取Channel中的數據,不能夠直接讀寫,必須經過Buffer
簡單來說:Channel通過Buffer(緩沖區)進行讀寫操作。read()表示讀取通道數據到緩沖區,write()表示把緩沖區數據寫入到通道。
Channel實現類
- FileChannel 和文件相關的通道
- DatagramChannel 和UDP協議傳輸數據相關的通道
- SocketChannel 和TCP協議相關的數據傳輸通道
- ServerSocket 和TCP協議相關的數據傳輸通道
- Pipe.SinkChannel、Pipe.SourceChannel //線程通信管道傳輸數據
Channel常用方法
- read() : 將Channel中的數據讀取到Buffer中
- write() : 向Buffer中寫入數據
- map(): 將channel中的數據全部或者部分映射到Buffer中(MappedByteBuffer,本質也是一個ByteBuffer),map()方法參數(讀寫模式,映射起始位置,數據長度)。
- inChannel.map(mode, position, size)
- MappedByteBuffer mappBuffer = inChannel.map(MapMode.READ_ONLY, 0, srcFile.length());
通道可以異步讀寫,異步讀寫表示通道執行讀寫操作時,也能做別的事情,解決線程阻塞。如果使用文件管道(FileChannel),建議用RandomAccessFile來創建管道,因為該類支持讀寫模式以及有大量處理文件的方法。
public static void main(String[] args) throws Exception {File f = new File("nio-a.txt");RandomAccessFile raf = new RandomAccessFile(f, "rw");FileChannel channel = raf.getChannel();MappedByteBuffer mapBuffer = channel.map(FileChannel.MapMode.READ_ONLY, 0, f.length());// raf.seek(f.length());channel.position(f.length());channel.write(mapBuffer);}Charset(字符集)
理解為現實生活的編碼表對象
當使用NIO來獲取文件內容時,如果是文本數據,那么需要進行轉碼,才能查看正確內容,這就需要解碼器。 如果要把字符數據寫入文件,需要將CharBuffer轉碼成ByteBuffer,這就需要編碼器。
- 包含了字節和 Unicode 字符之間轉換的 charset,還定義了用于創建解碼器和編碼器以及獲取與 charset 關聯的各種方法
- CharsetDecoder(解碼器):把字節轉成字符,例如查看文本數據,需要轉成字符才能查看,如果是字節,就看不懂了。
- CharsetEncoder(編碼器):把字符轉成字節,才能被計算機理解。 因為字節是計算機最小的存儲單位,所以Channel的IO操作都與ByteBuffer有關
- 解碼器和編碼器都不能直接創建,需要一個Charset對象來創建對應的解碼器和編碼器。
Charset常用方法
- forName():根據傳入的字符集獲得對應的字符集對象。
- defaultCharset():獲得當前使用的默認字符集。
- availableCharsets():獲得所有有效的字符集。
NIO遍歷文件
public static void main(String[] args) throws IOException {//匿名子對象實現FileVisitor接口FileVisitor<Path> visitor = new SimpleFileVisitor<Path>() {@Overridepublic FileVisitResult visitFile(Path path, BasicFileAttributes attrs) throws IOException {System.out.println("正在訪問" + path + "文件");if(path.endsWith("NIODemo.java")){System.out.println("恭喜您找到Java");return FileVisitResult.CONTINUE;}return FileVisitResult.CONTINUE;}@Overridepublic FileVisitResult preVisitDirectory(Path path, BasicFileAttributes attrs) throws IOException {System.out.println("準備訪問" + path + "文件");return FileVisitResult.CONTINUE;}@Overridepublic FileVisitResult visitFileFailed(Path path, IOException exc) throws IOException {System.out.println("準備訪問" + path + "文件失敗");System.out.println(exc.getMessage());return FileVisitResult.CONTINUE;}};//訪問文件樹Files.walkFileTree(Paths.get("D:\\JavaSE"), visitor);}以上
@Fzxey
轉載于:https://www.cnblogs.com/fzxey/p/10828465.html
總結
- 上一篇: ivew 双向绑定时间控件
- 下一篇: 软件开发冲刺3