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

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

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

  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. java压缩zip文件中文乱码问题(转——作者:riching)

    本人遇到了同样的问题,用了以下方案,奇迹般的解决了.我很纳闷为什么,经理说:好读书,不求甚解,不要问为什么... 用java来打包文件生成压缩文件,有两个地方会出现乱码 1.内容的中文乱码问题,这个问 ...

  2. Javascript实战开发:教你使用raphael.js绘制中国地图

    最近的数据统计项目中要用到中国地图,也就是在地图上动态的显示某个时间段某个省份地区的统计数据,我们不需要flash,仅仅依靠raphael.js以及SVG图像就可以完成地图的交互操作.在本文中,我给大 ...

  3. Spring Resource之内置的Resource实现

    Spring提供了大量的并且可以直接使用的Resource实现 1.UrlResource UrlResource封装了一个java.net.URL,而且可以通过一个URL用于访问任何对象,例如文件. ...

  4. 空间闹钟-v1.6更新!

    (假设图片无法显示可查看我的qq空间:http://user.qzone.qq.com/805853418/blog/1398785778) 生活助手系列--空间闹钟================= ...

  5. SQL Server的链接服务器(MySQL、Oracle、Ms_sql、Access、SYBASE)

    原文:SQL Server的链接服务器(MySQL.Oracle.Ms_sql.Access.SYBASE) 一.使用 Microsoft OLE DB Provider For ODBC 链接MyS ...

  6. Hibernate进化史-------Hibernate概要

    一个.Hibernate概要 什么是Hibernate呢?首先,Hibernate是数据持久层的一个轻量级框架.实现了ORMapping原理(Object Relational Mapping). 在 ...

  7. Effective C++ Item 46 当需要投你非成员函数定义模板

    本文senlie原版的,转载请保留此地址:http://blog.csdn.net/zhengsenlie 经验:当我们编写一个 class template, 而它所提供之"与此 temp ...

  8. 让Xcode Lua 语法高亮

    本人不太喜欢用code ide 还是喜欢XCODE的风格 1.让Xcode支援Lua语法高亮(Syntax Highlighting) 1. 下载https://github.com/breinhar ...

  9. screen获取屏幕信息

    <script type="text/javascript" language="javascript"> document.write(" ...

  10. NET框架SOA解决方案(集Windows服务、WinForm形式与IIS形式发布)-分布式应用

    NET框架SOA解决方案(集Windows服务.WinForm形式与IIS形式发布)-分布式应用 RDIFramework.NET,基于.NET的快速信息化系统开发.整合框架,给用户和开发者最佳的.N ...