将文件转为stream流_NIO之文件IO
? ? ?RandomAccessFile隨機IO在java中是一個重要的IO類,與傳統的IO類相比有很多特點:
? ? 1.集成了IO讀寫方法,運用這個類就可以對文件內容進行讀寫操作。
? ? 2. ? getFilePointer()方法,可以獲取當前文件讀取/寫入的位子,類似于獲取文件中當前光標位置。
? ? 3. ? seek(pos),指定文件的光標位置,通俗點說就是指定你的光標位置然后下次讀文件數據的時候從該位置讀取。
有了這個特性,可以實現一些操作,例如文件斷點續傳:文件下載過程中網斷了,記錄文件下載位置下次網連接上了直接從該位置開始下載;
多線程下載文件:或將一個大的文件分成多個部分,然后用多線程每個線程負責讀取/寫入其中一段。
? ?4.? FileChannel?它返回的就是nio通信中的file的唯一channel
RandomAccessFile raf= new RandomAccessFile("filePath","rw");FileChannel fileChannel = raf.getChannel();???? java ?NIO核心組成是:
? ? ? ? 1). ?channel:管道,與stream相比它是雙向的,是面向緩沖區ByteBuffer的,對應于stream的輸入流,是ByteBuffer從channel讀入數據,對應于stream的輸出流,是ByteBuffer從channel寫出數據?。
inputstream? ---->fileChannel.read(buf)
outputstream? ----->fileChannel.write(buf)
? ? ? ? ? 2). ? ByteBuffer緩存區,大致分為三類:
ByteBuffer/DirectByteBuffer/MappedByteBufferByteBuffer:ByteBuffer.allocate(1024); 是存儲在JVM堆空間的緩存區,優點是java用戶態創建,????????????創建速度快,有jvm垃圾回收機制控制緩存區的回收。????????????缺點是占用jvm堆空間內存,增加jvm垃圾回收負擔,????????????在文件上傳或下載時需要調用操作系統read()/write()????????????函數,將緩存區數據copy到用戶態內存空間(如read())/????????????內核態內存空間(如write()函數),IO操作效率不高,????????????尤其是大文件。?DirectByteBuffer:ByteBuffer.allocateDirect(1024);????????????是在堆外申請了內存,緩存區存儲在內核態內存中而不在????????????堆空間,通過虛擬內存地址,直接操作內核態內存空間????????????緩存區數據,IO操作不需要調用read()/write()系統????????????函數(0copy操作),并且不占用堆空間內存。??????????? java是通過調用unsafe類實現的。MappedByteBuffer:虛擬內存映射,通過虛擬內存地址操作系統內存空間??????????????????緩存區數據,利用操作系統的內存的缺頁中斷機制??????????????????來加載文件系統的數據到內存中,MappedByteBuffer??????????????????是個抽象類,其實現類是DirectByteBuffer。實際??????????????????操作的類也是DirectByteBuffer類。? ? ? ?在進行文件上傳下載時應用?DirectByteBuffer/MappedByteBuffer,不僅
逼格很高,而且速度也會得到提高,尤其是對于大型文件。
? ??3)? ?Selector待續。。。
FileChannel代碼示例:
? ? 1)DirectByteBuffer上傳文件
RandomAccessFile raf = null;try {raf = new RandomAccessFile("test.txt", "rw"); //獲取fileChannelFileChannel fileChannel = raf.getChannel();// 申請直接內存,大小1024字節ByteBuffer buf = ByteBuffer.allocateDirect(1024);// ByteBuffer讀入數據int bytesRead = fileChannel.read(buf);while (bytesRead != -1) {// ByteBuffer由讀狀態轉為寫狀態 buf.flip();while (buf.hasRemaining()) {// buf獲取數據 System.out.print((char) buf.get());}????????????// ????//壓縮此緩沖區,將buffer中未讀取的數據移到buffer前面?// ???????????????//將光標指向最后一個沒有讀取的下一個位置 buf.compact();// buf讀數據,向buf寫數據 bytesRead = fileChannel.read(buf);}} catch (IOException e) {e.printStackTrace();} finally {try {if (aFile != null) {aFile.close();}} catch (IOException e) {e.printStackTrace();}?}? ? ?2)MappedByteBuffer 下載文件
RandomAccessFile raf = new RandomAccessFile("test.txt", "rw");FileChannel fileChannel = raf.getChannel();String msg = "你好,world!";// 內存映射區域總大小 long size = msg.getBytes().length * COUNT;//READ_WRITE可以讀寫的ByteBufferMappedByteBuffer map = fileChannel.map(FileChannel.MapMode.READ_WRITE, 0, size);for (int i = 0; i < COUNT; i++) {map.put(msg.getBytes());raf.close();}? ? ? ? 3)補充:
? ? ?a)使用DirectByteBuffer/MappedByteBuffer,文件是存儲在操作系統緩存頁cachePage,寫入磁盤是由操作系統控制的,如果cachePage還沒有刷新到磁盤,如果系統正常關機,那么cachePage會刷到磁盤后再關機沒有問題,但是如果是操作系統斷電了,那就悲劇了!因為一些cachePage沒寫入磁盤,會導致一些文件丟失。
解決:1.通過命令將pageCache刷新到磁盤,但是會影響系統性能
? ? ? ? ? ?2.啥都不用管,依賴操作系統,效率佳,可能是斷電這事比較少見吧。
? ? ?b)虛擬內存是啥?
? ? ? ?虛擬內存是操作系統的內存管理機制,linux操作系統為每個系統進程如java進程,分配一個虛擬內存,虛擬內存是邏輯內存,理論大小是2^32(32位操作系統),2^64(64位操作系統)。虛擬內存與實際物理內存是通過虛擬內存地址(邏輯地址)+MMU(內存管理硬件)得出實際物理內存地址。
總結
以上是生活随笔為你收集整理的将文件转为stream流_NIO之文件IO的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Mybatis generator 1.
- 下一篇: RandomAccessFile简介与使