大多数操作系统都可以利用虚拟内存实现将一个文件或者文件的一部分"映射"到内存中。然后,这个文件就可以当作是内存数组来访问,这比传统的文件要快得多。

内存映射文件的一个关键优势是操作系统负责真正的读写,即使你的程序在刚刚写入内存后就挂了,操作系统仍然会将内存中的数据写入文件系统。另外一个更突出的优势是共享内存,内存映射文件可以被多个进程同时访问,起到一种低时延共享内存的作用。

那么,如何将一个文件映射到内存呢?

  1. 从文件中获得一个通道(channel)
FileChannel channel = FileChannel.open(path,options);

这里options指定映射模式,支持的模式有三种:

  • FileChannel.MapMode.READ_ONLY:所产生的缓冲区是只读的。
  • FileChannel.MapMode.READ_WRITE:所产生的缓冲区是可写的,任何修改都会在某个时刻写回到文件中。

    注意,其他映射同一个文件的程序可能不能立即看到这些修改,多个程序同时进行文件映射的确切行为是依赖

    于操作系统的。
  • FileChannel.MapMode.PRIVATE:所产生的缓冲区是可写的,但是任何修改对该缓冲区来说都是私有的,不

    会传播到文件中。
  1. 调用FileChannel的map方法
MappedByteBuffer buffer = channel.map(FileChannel.MapMode.READ_ONLY,0,length);

接下来通过计算一个40MB文件的CRC32校验和来比较传统的文件输入和内存映射文件的速度。

传统的文件输入包括:

  • 普通输入流(InputStream)
  • 带缓冲的输入流(BufferedInputStream)
  • 随机访问文件(RandomAccessFile)

程序如下:

import java.io.*;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.zip.CRC32; /**
* Created by lbd on 2017/1/11.
*/
public class MemoryMapTest {
public static long checksumInputStream(Path filename) throws IOException { //普通输入流
try (InputStream in = Files.newInputStream(filename)) {
CRC32 crc = new CRC32();
int c;
while ((c = in.read()) != -1)
crc.update(c);
return crc.getValue();
}
} public static long checksumBufferedInputStream(Path filename) throws IOException { //带缓冲的输入流
try (BufferedInputStream in = new BufferedInputStream(Files.newInputStream(filename))){
CRC32 crc = new CRC32();
int c;
while ((c = in.read()) != -1)
crc.update(c);
return crc.getValue();
}
} public static long checksumRandomAccessFile(Path filename) throws IOException { //随机访问文件
try (RandomAccessFile file = new RandomAccessFile(filename.toFile(),"r")){
CRC32 crc = new CRC32();
long length = file.length(); for (long p = 0; p < length; p++){
file.seek(p);
int c = file.readByte();
crc.update(c);
}
return crc.getValue();
}
} public static long checksumMappedFile(Path filename) throws IOException { //内存映射文件
try (FileChannel channel = FileChannel.open(filename)){
CRC32 crc = new CRC32();
int length = (int)channel.size();
MappedByteBuffer buffer = channel.map(FileChannel.MapMode.READ_ONLY,0,length); for (int p = 0; p < length; p++){
int c = buffer.get(p);
crc.update(c);
}
return crc.getValue();
}
} public static void main(String[] args) throws IOException {
System.out.println("Input Stream:");
long start = System.currentTimeMillis();
Path filename = Paths.get(args[0]);
long crcValue = checksumInputStream(filename);
long end = System.currentTimeMillis();
System.out.println(Long.toHexString(crcValue));
System.out.println((end - start) + " milliseconds");
System.out.println(); System.out.println("Buffered Input Stream:");
start = System.currentTimeMillis();
crcValue = checksumBufferedInputStream(filename);
end = System.currentTimeMillis();
System.out.println(Long.toHexString(crcValue));
System.out.println((end - start) + " milliseconds");
System.out.println(); System.out.println("Random Access File:");
start = System.currentTimeMillis();
crcValue = checksumRandomAccessFile(filename);
end = System.currentTimeMillis();
System.out.println(Long.toHexString(crcValue));
System.out.println((end - start) + " milliseconds");
System.out.println(); System.out.println("Mapped File:");
start = System.currentTimeMillis();
crcValue = checksumMappedFile(filename);
end = System.currentTimeMillis();
System.out.println(Long.toHexString(crcValue));
System.out.println((end - start) + " milliseconds");
}
}

输出结果如下:

Input Stream:
c644b1f1
42317 milliseconds Buffered Input Stream:
c644b1f1
329 milliseconds Random Access File:
c644b1f1
57781 milliseconds Mapped File:
c644b1f1
207 milliseconds

可以明显看出,内存映射文件速度比普通输入流和随机访问文件快得多,比带缓冲的输入流稍微快一些。

Java NIO之内存映射文件——MappedByteBuffer的更多相关文章

  1. JAVA NIO FileChannel 内存映射文件

      文件通道总是阻塞式的. 文件通道不能创建,只能通过(RandomAccessFile.FileInputStream.FileOutputStream)getChannel()获得,具有与File ...

  2. 内存映射文件MappedByteBuffer和Buffer的Scattering与Gathering

    上一篇讲到的DirectByteBuffer继承自MappedByteBuffer 一.MappedByteBuffer MappedByteBuffer的定义: A direct byte buff ...

  3. JAVA NIO之浅谈内存映射文件原理与DirectMemory

    JAVA类库中的NIO包相对于IO 包来说有一个新功能是内存映射文件,日常编程中并不是经常用到,但是在处理大文件时是比较理想的提高效率的手段.本文我主要想结合操作系统中(OS)相关方面的知识介绍一下原 ...

  4. NIO之通道(Channel)的原理与获取以及数据传输与内存映射文件

    通道(Channel) 由java.nio.channels包定义的,Channel表示IO源与目标打开的连接,Channel类似于传统的“流”,只不过Channel本身不能直接访问数据,Channe ...

  5. Java-NIO(五):通道(Channel)的数据传输与内存映射文件

    通道(Channel)的数据传输(采用非直接缓冲区) @Test public void testChannel() throws IOException { FileInputStream file ...

  6. 内存映射文件(Memory-Mapped File)

    Java Memory-Mapped File所使用的内存分配在物理内存而不是JVM堆内存,且分配在OS内核. 1: 内存映射文件及其应用 - 实现一个简单的消息队列 / 计算机程序的思维逻辑 在一般 ...

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

    内存映射文件能让你创建和修改那些因为太大而无法放入内存的文件.有了内存映射文件,你就可以认为文件已经全部读进了内存,然后把它当成一个非常大的数组来访问.这种解决办法能大大简化修改文件的代码.fileC ...

  8. Java NIO 内存映射文件

    Java NIO 内存映射文件 @author ixenos 文件操作的四大方法 前提:内存的访问速度比磁盘高几个数量级,但是基本的IO操作是直接调用native方法获得驱动和磁盘交互的,IO速度限制 ...

  9. Java编程的逻辑 (61) - 内存映射文件及其应用 - 实现一个简单的消息队列

    本系列文章经补充和完善,已修订整理成书<Java编程的逻辑>,由机械工业出版社华章分社出版,于2018年1月上市热销,读者好评如潮!各大网店和书店有售,欢迎购买,京东自营链接:http:/ ...

随机推荐

  1. CSS知识总结之设计模式(持续学习中)

    OOCSS 参考:http://coding.smashingmagazine.com/2011/12/12/an-introduction-to-object-oriented-css-oocss  ...

  2. selenium2入门 用Yaml文件进行元素管理 (五)

    比如界面有一个按钮,id号是test.如果进行对象化的话,就是test.click就可以了.不用每次都要去创建test对象.如果id号变了,我们也只需要改一下test的名称就行了. 使用Yaml需要用 ...

  3. lua及luci学习

    由于项目需要对Luci进行修改,所以这里开始地luci进行较深入的研究. 探索其中的运行路径. Openwrt默认的HTTP服务器为uhttpd,该WEB服务器是由Luci的开发者自行开发的,非常小巧 ...

  4. FFT 的C 语言

    FFT 的C 语言 说好的C 语言实现.必须搞定它! 理论介绍: http://blog.csdn.net/cinmyheart/article/details/39052739 这里有之前matla ...

  5. Windows在结构FTPserver

    同Windows8 案件,结构介绍 FTPserver脚步: 1.为Windows开启FTP功能:控制面板->程序->启用或关闭Windows功能.将下图所看到的的复选框选中 waterm ...

  6. .net操作PDF的一些资源(downmoon收集)

    因为业务需要,搜集了一些.net操作pdf的一些资源,特在此分享. 1.如何从 Adobe 可移植文档格式 (PDF) 文件中复制文本和图形 http://support.microsoft.com/ ...

  7. leetcode[91] Subsets II

    给定一个数组,返回所有的非重复的可能.例如给定 If S = [1,2,2], a solution is: [ [2], [1], [1,2,2], [2,2], [1,2], [] ] 其实这题类 ...

  8. linux下搭建SVN服务器完全手册-很强大!!!!!

    系统环境        RHEL5.4最小化安装(关iptables,关selinux) + ssh + yum 一,安装必须的软件包.        yum install subversion ( ...

  9. Flex 弹性盒模型

    <!doctype html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  10. D12

    orz!=-=今天莫名爆人品..表示受到了惊吓.. 一下子从rank20-30+,突然间蹦到了rank3..=-=可怕.. 或许是因为T1有看过啊类似的啊..然后T3又被40指点了一下,T2打了个暴力 ...