日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > java >内容正文

java

【JavaNIO的深入研究4】内存映射文件I/O,大文件读写操作,Java nio之MappedByteBuffer,高效文件/内存映射...

發(fā)布時(shí)間:2025/3/15 java 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【JavaNIO的深入研究4】内存映射文件I/O,大文件读写操作,Java nio之MappedByteBuffer,高效文件/内存映射... 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

內(nèi)存映射文件能讓你創(chuàng)建和修改那些因?yàn)樘蠖鵁o(wú)法放入內(nèi)存的文件。有了內(nèi)存映射文件,你就可以認(rèn)為文件已經(jīng)全部讀進(jìn)了內(nèi)存,然后把它當(dāng)成一個(gè)非常大的數(shù)組來(lái)訪問(wèn)。這種解決辦法能大大簡(jiǎn)化修改文件的代碼。
fileChannel.map(FileChannel.MapMode mode, long position, long size)將此通道的文件區(qū)域直接映射到內(nèi)存中。注意,你必須指明,它是從文件的哪個(gè)位置開(kāi)始映射的,映射的范圍又有多大;也就是說(shuō),它還可以映射一個(gè)大文件的某個(gè)小片斷。


MappedByteBuffer是ByteBuffer的子類(lèi),因此它具備了ByteBuffer的所有方法,但新添了force()將緩沖區(qū)的內(nèi)容強(qiáng)制刷新到存儲(chǔ)設(shè)備中去、load()將存儲(chǔ)設(shè)備中的數(shù)據(jù)加載到內(nèi)存中、isLoaded()位置內(nèi)存中的數(shù)據(jù)是否與存儲(chǔ)設(shè)置上同步。這里只簡(jiǎn)單地演示了一下put()和get()方法,除此之外,你還可以使用asCharBuffer( )之類(lèi)的方法得到相應(yīng)基本類(lèi)型數(shù)據(jù)的緩沖視圖后,可以方便的讀寫(xiě)基本類(lèi)型數(shù)據(jù)。

?

內(nèi)存映射文件 I/O 是一種讀和寫(xiě)文件數(shù)據(jù)的方法,它可以比常規(guī)的基于流或者基于通道的 I/O 快得多。

內(nèi)存映射文件 I/O 是通過(guò)使文件中的數(shù)據(jù)神奇般地出現(xiàn)為內(nèi)存數(shù)組的內(nèi)容來(lái)完成的。這其初聽(tīng)起來(lái)似乎不過(guò)就是將整個(gè)文件讀到內(nèi)存中,但是事實(shí)上并不是這樣。一般來(lái)說(shuō),只有文件中實(shí)際讀取或者寫(xiě)入的部分才會(huì)送入(或者?映射?)到內(nèi)存中。

內(nèi)存映射并不真的神奇或者多么不尋常。現(xiàn)代操作系統(tǒng)一般根據(jù)需要將文件的部分映射為內(nèi)存的部分,從而實(shí)現(xiàn)文件系統(tǒng)。Java 內(nèi)存映射機(jī)制不過(guò)是在底層操作系統(tǒng)中可以采用這種機(jī)制時(shí),提供了對(duì)該機(jī)制的訪問(wèn)。

盡管創(chuàng)建內(nèi)存映射文件相當(dāng)簡(jiǎn)單,但是向它寫(xiě)入可能是危險(xiǎn)的。僅只是改變數(shù)組的單個(gè)元素這樣的簡(jiǎn)單操作,就可能會(huì)直接修改磁盤(pán)上的文件。修改數(shù)據(jù)與將數(shù)據(jù)保存到磁盤(pán)是沒(méi)有分開(kāi)的。

?

(1)了解內(nèi)存映射的最好方法是使用例子。在下面的例子中,我們要將一個(gè)?FileChannel?(它的全部或者部分)映射到內(nèi)存中。為此我們將使用?FileChannel.map()?方法。下面代碼行將文件的前 1024 個(gè)字節(jié)映射到內(nèi)存中:

public class UseMappedFile {static private final int start = 0;static private final int size = 1024;static public void main( String args[] ) throws Exception {RandomAccessFile raf = new RandomAccessFile( "usemappedfile.txt", "rw" );FileChannel fc = raf.getChannel();MappedByteBuffer mbb = fc.map( FileChannel.MapMode.READ_WRITE,start, size );mbb.put( 0, (byte)97 );mbb.put( 1023, (byte)122 );for (int i = start; i < size; i++) { System.out.print((char) mbb.get(i)); } raf.close();} }

運(yùn)行結(jié)果:

(2)該程序創(chuàng)建了一個(gè)128Mb的文件,如果一次性讀到內(nèi)存可能導(dǎo)致內(nèi)存溢出,但這里訪問(wèn)好像只是一瞬間的事,這是因?yàn)?#xff0c;真正調(diào)入內(nèi)存的只是其中的一小部分,其余部分則被放在交換文件上。這樣你就可以很方便地修改超大型的文件了(最大可以到2 GB)。注意,Java是調(diào)用操作系統(tǒng)的"文件映射機(jī)制"來(lái)提升性能的。

public class LargeMappedFiles { static int length = 0x8000000; // 128 Mb public static void main(String[] args) throws Exception { // 為了以可讀可寫(xiě)的方式打開(kāi)文件,這里使用RandomAccessFile來(lái)創(chuàng)建文件。 FileChannel fc = new RandomAccessFile("test.dat", "rw").getChannel(); //注意,文件通道的可讀可寫(xiě)要建立在文件流本身可讀寫(xiě)的基礎(chǔ)之上 MappedByteBuffer out = fc.map(FileChannel.MapMode.READ_WRITE, 0, length); //寫(xiě)128M的內(nèi)容 for (int i = 0; i < length; i++) { out.put((byte) 'x'); } System.out.println("Finished writing"); //讀取文件中間6個(gè)字節(jié)內(nèi)容 for (int i = length / 2; i < length / 2 + 6; i++) { System.out.print((char) out.get(i)); } fc.close(); } }

運(yùn)行結(jié)果:

Finished writing
xxxxxx

?(3)java處理大文件,一般用BufferedReader,BufferedInputStream這類(lèi)帶緩沖的Io類(lèi),不過(guò)如果文件超大的話,更快的方式是采用MappedByteBuffer。

三種方式:
????????????? FileChannel提供了map方法來(lái)把文件影射為內(nèi)存映像文件: MappedByteBuffer map(int mode,long position,long size); 可以把文件的從position開(kāi)始的size大小的區(qū)域映射為內(nèi)存映像文件,mode指出了 可訪問(wèn)該內(nèi)存映像文件的方式:READ_ONLY,READ_WRITE,PRIVATE.???????

?????????????
a. READ_ONLY,(只讀): 試圖修改得到的緩沖區(qū)將導(dǎo)致拋出 ReadOnlyBufferException.(MapMode.READ_ONLY)


?b. READ_WRITE(讀/寫(xiě)): 對(duì)得到的緩沖區(qū)的更改最終將傳播到文件;該更改對(duì)映射到同一文件的其他程序不一定是可見(jiàn)的。 (MapMode.READ_WRITE)


c. PRIVATE(專(zhuān)用): 對(duì)得到的緩沖區(qū)的更改不會(huì)傳播到文件,并且該更改對(duì)映射到同一文件的其他程序也不是可見(jiàn)的;相反,會(huì)創(chuàng)建緩沖區(qū)已修改部分的專(zhuān)用副本。 (MapMode.PRIVATE)

三個(gè)方法:

a. fore();緩沖區(qū)是READ_WRITE模式下,此方法對(duì)緩沖區(qū)內(nèi)容的修改強(qiáng)行寫(xiě)入文件
b. load()將緩沖區(qū)的內(nèi)容載入內(nèi)存,并返回該緩沖區(qū)的引用
c. isLoaded()如果緩沖區(qū)的內(nèi)容在物理內(nèi)存中,則返回真,否則返回假

三個(gè)特性:

??? 調(diào)用信道的map()方法后,即可將文件的某一部分或全部映射到內(nèi)存中,映射內(nèi)存緩沖區(qū)是個(gè)直接緩沖區(qū),繼承自ByteBuffer,但相對(duì)于ByteBuffer,它有更多的優(yōu)點(diǎn):

a. 讀取快
b. 寫(xiě)入快
c. 隨時(shí)隨地寫(xiě)入

package study; import java.io.FileInputStream; import java.io.FileOutputStream; import java.nio.ByteBuffer; import java.nio.MappedByteBuffer; import java.nio.channels.FileChannel; public class MapMemeryBuffer { public static void main(String[] args) throws Exception { ByteBuffer byteBuf = ByteBuffer.allocate(1024 * 14 * 1024); byte[] bbb = new byte[14 * 1024 * 1024]; FileInputStream fis = new FileInputStream("e://data/other/UltraEdit_17.00.0.1035_SC.exe"); FileOutputStream fos = new FileOutputStream("e://data/other/outFile.txt"); FileChannel fc = fis.getChannel(); long timeStar = System.currentTimeMillis();// 得到當(dāng)前的時(shí)間 fc.read(byteBuf);// 1 讀取 //MappedByteBuffer mbb = fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size()); System.out.println(fc.size()/1024); long timeEnd = System.currentTimeMillis();// 得到當(dāng)前的時(shí)間 System.out.println("Read time :" + (timeEnd - timeStar) + "ms"); timeStar = System.currentTimeMillis(); fos.write(bbb);//2.寫(xiě)入 //mbb.flip(); timeEnd = System.currentTimeMillis(); System.out.println("Write time :" + (timeEnd - timeStar) + "ms"); fos.flush(); fc.close(); fis.close(); } } 運(yùn)行結(jié)果: 14235 Read time :24ms Write time :21ms 我們把標(biāo)注1和2語(yǔ)句注釋掉,換成它們下面的被注釋的那條語(yǔ)句,再來(lái)看運(yùn)行效果。14235 Read time :2ms Write time :0ms

可以看出速度有了很大的提升。MappedByteBuffer的確快,但也存在一些問(wèn)題,主要就是內(nèi)存占用和文件關(guān)閉等不確定問(wèn)題。被MappedByteBuffer打開(kāi)的文件只有在垃圾收集時(shí)才會(huì)被關(guān)閉,而這個(gè)點(diǎn)是不確定的。在javadoc里是這么說(shuō)的:A mapped byte buffer and the file mapping that it represents remain valid until the buffer itself? is garbage-collected.

轉(zhuǎn)自:http://langgufu.iteye.com/blog/2107023

轉(zhuǎn)載于:https://www.cnblogs.com/guweiwei/p/6529384.html

總結(jié)

以上是生活随笔為你收集整理的【JavaNIO的深入研究4】内存映射文件I/O,大文件读写操作,Java nio之MappedByteBuffer,高效文件/内存映射...的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。