Java NIO之内存映射文件——MappedByteBuffer
大多数操作系统都可以利用虚拟内存实现将一个文件或者文件的一部分"映射"到内存中。然后,这个文件就可以当作是内存数组来访问,这比传统的文件要快得多。
内存映射文件的一个关键优势是操作系统负责真正的读写,即使你的程序在刚刚写入内存后就挂了,操作系统仍然会将内存中的数据写入文件系统。另外一个更突出的优势是共享内存,内存映射文件可以被多个进程同时访问,起到一种低时延共享内存的作用。
那么,如何将一个文件映射到内存呢?
- 从文件中获得一个通道(channel)
FileChannel channel = FileChannel.open(path,options);
这里options指定映射模式,支持的模式有三种:
- FileChannel.MapMode.READ_ONLY:所产生的缓冲区是只读的。
- FileChannel.MapMode.READ_WRITE:所产生的缓冲区是可写的,任何修改都会在某个时刻写回到文件中。
注意,其他映射同一个文件的程序可能不能立即看到这些修改,多个程序同时进行文件映射的确切行为是依赖
于操作系统的。 - FileChannel.MapMode.PRIVATE:所产生的缓冲区是可写的,但是任何修改对该缓冲区来说都是私有的,不
会传播到文件中。
- 调用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的更多相关文章
- JAVA NIO FileChannel 内存映射文件
文件通道总是阻塞式的. 文件通道不能创建,只能通过(RandomAccessFile.FileInputStream.FileOutputStream)getChannel()获得,具有与File ...
- 内存映射文件MappedByteBuffer和Buffer的Scattering与Gathering
上一篇讲到的DirectByteBuffer继承自MappedByteBuffer 一.MappedByteBuffer MappedByteBuffer的定义: A direct byte buff ...
- JAVA NIO之浅谈内存映射文件原理与DirectMemory
JAVA类库中的NIO包相对于IO 包来说有一个新功能是内存映射文件,日常编程中并不是经常用到,但是在处理大文件时是比较理想的提高效率的手段.本文我主要想结合操作系统中(OS)相关方面的知识介绍一下原 ...
- NIO之通道(Channel)的原理与获取以及数据传输与内存映射文件
通道(Channel) 由java.nio.channels包定义的,Channel表示IO源与目标打开的连接,Channel类似于传统的“流”,只不过Channel本身不能直接访问数据,Channe ...
- Java-NIO(五):通道(Channel)的数据传输与内存映射文件
通道(Channel)的数据传输(采用非直接缓冲区) @Test public void testChannel() throws IOException { FileInputStream file ...
- 内存映射文件(Memory-Mapped File)
Java Memory-Mapped File所使用的内存分配在物理内存而不是JVM堆内存,且分配在OS内核. 1: 内存映射文件及其应用 - 实现一个简单的消息队列 / 计算机程序的思维逻辑 在一般 ...
- 【JavaNIO的深入研究4】内存映射文件I/O,大文件读写操作,Java nio之MappedByteBuffer,高效文件/内存映射
内存映射文件能让你创建和修改那些因为太大而无法放入内存的文件.有了内存映射文件,你就可以认为文件已经全部读进了内存,然后把它当成一个非常大的数组来访问.这种解决办法能大大简化修改文件的代码.fileC ...
- Java NIO 内存映射文件
Java NIO 内存映射文件 @author ixenos 文件操作的四大方法 前提:内存的访问速度比磁盘高几个数量级,但是基本的IO操作是直接调用native方法获得驱动和磁盘交互的,IO速度限制 ...
- Java编程的逻辑 (61) - 内存映射文件及其应用 - 实现一个简单的消息队列
本系列文章经补充和完善,已修订整理成书<Java编程的逻辑>,由机械工业出版社华章分社出版,于2018年1月上市热销,读者好评如潮!各大网店和书店有售,欢迎购买,京东自营链接:http:/ ...
随机推荐
- 使用Row_Number()分页优化
记一次SQLServer的分页优化兼谈谈使用Row_Number()分页存在的问题 最近有项目反应,在服务器CPU使用较高的时候,我们的事件查询页面非常的慢,查询几条记录竟然要4分钟甚至更长,而且 ...
- 有趣的游戏:Google XSS Game
Google最近出了一XSS游戏: https://xss-game.appspot.com/ 我这个菜鸟看提示,花了两三个小时才全过了.. 这个游戏的规则是仅仅要在攻击网页上弹出alert窗体就能够 ...
- C语言内存对齐(2)
前两天参加了360测试实习生的笔试,碰到了一个有关c语言内存对齐的题目,回来后实现了一下,下面是代码: #include <stdio.h> #include <stdlib.h&g ...
- iSwifting社区【www.iSwifting.com】招聘版主
iSwifting社区[www.iSwifting.com]昨天找来几个主持人.我已经被任命为他们的任务领域. 他们有百度的project噢,还有cocoaChina问答区的活跃人物! 欢迎大家一起学 ...
- android:Fragment动画的东西
最近很多人来Fragment动画是很感兴趣,我将是一个样本给大家看. 既然做,我会做动画以下类型: 注入弹出动画:从""进入.从"上下左右"弹出,当然,你怎么组 ...
- solr的安装与配置
solr的安装与配置 不久之前开发了一个项目,需要用到solr,因为所以在开始再网上查找资料,但是发现大部分的资料都是很片面的,要么就是只讲解solr如何安装的,要么就是只讲解solr的某一个部分的, ...
- .NET Framework和C#版本历史概览
发布日期 .Net版本 C#版本 CLR版本 开发工具 功能介绍 2002 1.0 1.0 初始版本 Visual Studio .Net 初始版本 .NET框架结构,详见: 2003 1.1 ...
- wcf消息模式(随记)
----------------------------------------------消息模式:1.request\reply(默认)2.one-way(单工)[Isoneway=true]客户 ...
- ASP.NET SignalR 2.0入门指南
ASP.NET SignalR 2.0入门指南 介绍SignalR ASP.NET SignalR 是一个为 ASP.NET 开发人员的库,简化了将实时 web 功能添加到应用程序的过程.实时Web功 ...
- C++ Builder中TOpenDialog控件的使用例子
源代码如下(opendlg_loaddata为TOpenDialog控件的name,ofAllowMultiSelect代表允许多选): opendlg_loaddata->Options &l ...