記憶體映射檔案能讓你建立和修改那些因為太大而無法放入記憶體的檔案。有了記憶體映射檔案,你就可以認為檔案已經全部讀進了記憶體,然後把它當成一個非常大的數組來通路。這種解決辦法能大大簡化修改檔案的代碼。
fileChannel.map(FileChannel.MapMode mode, long position, long size)将此通道的檔案區域直接映射到記憶體中。注意,你必須指明,它是從檔案的哪個位置開始映射的,映射的範圍又有多大;也就是說,它還可以映射一個大檔案的某個小片斷。
MappedByteBuffer是ByteBuffer的子類,是以它具備了ByteBuffer的所有方法,但新添了force()将緩沖區的内容強制重新整理到儲存設備中去、load()将儲存設備中的資料加載到記憶體中、isLoaded()位置記憶體中的資料是否與存儲設定上同步。這裡隻簡單地示範了一下put()和get()方法,除此之外,你還可以使用asCharBuffer( )之類的方法得到相應基本類型資料的緩沖視圖後,可以友善的讀寫基本類型資料。
記憶體映射檔案 I/O 是一種讀和寫檔案資料的方法,它可以比正常的基于流或者基于通道的 I/O 快得多。
記憶體映射檔案 I/O 是通過使檔案中的資料神奇般地出現為記憶體數組的内容來完成的。這其初聽起來似乎不過就是将整個檔案讀到記憶體中,但是事實上并不是這樣。一般來說,隻有檔案中實際讀取或者寫入的部分才會送入(或者 映射 )到記憶體中。
記憶體映射并不真的神奇或者多麼不尋常。現代作業系統一般根據需要将檔案的部分映射為記憶體的部分,進而實作檔案系統。Java 記憶體映射機制不過是在底層作業系統中可以采用這種機制時,提供了對該機制的通路。
盡管建立記憶體映射檔案相當簡單,但是向它寫入可能是危險的。僅隻是改變數組的單個元素這樣的簡單操作,就可能會直接修改磁盤上的檔案。修改資料與将資料儲存到磁盤是沒有分開的。
(1)了解記憶體映射的最好方法是使用例子。在下面的例子中,我們要将一個 <code>FileChannel</code> (它的全部或者部分)映射到記憶體中。為此我們将使用 <code>FileChannel.map()</code> 方法。下面代碼行将檔案的前 1024 個位元組映射到記憶體中:


運作結果:
(2)該程式建立了一個128Mb的檔案,如果一次性讀到記憶體可能導緻記憶體溢出,但這裡通路好像隻是一瞬間的事,這是因為,真正調入記憶體的隻是其中的一小部分,其餘部分則被放在交換檔案上。這樣你就可以很友善地修改超大型的檔案了(最大可以到2 GB)。注意,Java是調用作業系統的"檔案映射機制"來提升性能的。


Finished writing
xxxxxx
(3)java處理大檔案,一般用BufferedReader,BufferedInputStream這類帶緩沖的Io類,不過如果檔案超大的話,更快的方式是采用MappedByteBuffer。
三種方式:
FileChannel提供了map方法來把檔案影射為記憶體映像檔案: MappedByteBuffer map(int mode,long position,long size); 可以把檔案的從position開始的size大小的區域映射為記憶體映像檔案,mode指出了 可通路該記憶體映像檔案的方式:READ_ONLY,READ_WRITE,PRIVATE.
a. READ_ONLY,(隻讀): 試圖修改得到的緩沖區将導緻抛出 ReadOnlyBufferException.(MapMode.READ_ONLY)
b. READ_WRITE(讀/寫): 對得到的緩沖區的更改最終将傳播到檔案;該更改對映射到同一檔案的其他程式不一定是可見的。 (MapMode.READ_WRITE)
c. PRIVATE(專用): 對得到的緩沖區的更改不會傳播到檔案,并且該更改對映射到同一檔案的其他程式也不是可見的;相反,會建立緩沖區已修改部分的專用副本。 (MapMode.PRIVATE)
三個方法:
a. fore();緩沖區是READ_WRITE模式下,此方法對緩沖區内容的修改強行寫入檔案
b. load()将緩沖區的内容載入記憶體,并傳回該緩沖區的引用
c. isLoaded()如果緩沖區的内容在實體記憶體中,則傳回真,否則傳回假
三個特性:
調用信道的map()方法後,即可将檔案的某一部分或全部映射到記憶體中,映射記憶體緩沖區是個直接緩沖區,繼承自ByteBuffer,但相對于ByteBuffer,它有更多的優點:
a. 讀取快
b. 寫入快
c. 随時随地寫入


可以看出速度有了很大的提升。MappedByteBuffer的确快,但也存在一些問題,主要就是記憶體占用和檔案關閉等不确定問題。被MappedByteBuffer打開的檔案隻有在垃圾收集時才會被關閉,而這個點是不确定的。在javadoc裡是這麼說的:A mapped byte buffer and the file mapping that it represents remain valid until the buffer itself is garbage-collected.