处理文件是java经常使用的操作,在对一个“大文件”(比如超过64M)进行操作时一点点速度的提高都会带来性能的巨大提升。然而我们经常使用的BufferxxStream,来直接处理大文件时,往往力不从心。

  java中“映射文件访问”机制则解决了这一问题,它把大文件的较小部分先放在内存里,将其余待读取的数据仍然放在硬盘里面。但是我们完全可以通过这样一个机制把这个大文件当作非常大的数组来使用。是不是很像操作系统里面对于应用的使用方法?没错,其实java正是利用了底层操作系统的文件映射工具来最大化提高性能。

  一般为了即能读又能写,我们使用RandomAccessFile来进行测试,同过该文件上的通道,然后调用FileChannel中的map()所产生的MappedByteBuffer,在map方法中有三个参数map(FileChannel.MapMode mode, long position, long size)。

  其中mode 来决定映射的文件访问的读/写机制,可以设置MapMode.READ_ONLY, MapMode.READ_WRITEMapMode.PRIVATE,通过名字可以看得出他们的作用,特别要注意MapMode.PRIVATE方法,如何你操作不当会导致你操作的文件无法被共享。

  而position为区域内的文件映射的位置开始,必须是非负数

  size为区域的大小是映射;必须是非负数,不大于Integer.MAX_VALUE

  其实position和size的设置就意味着我们映射某个大文件的较小的部分

  下面就来看我们使用了“映射文件访问”时,的性能提升把!

  以下是代码部分:

 package com.company;

 import java.io.*;
import java.nio.IntBuffer;
import java.nio.channels.FileChannel; /**
* Created by chunmiao on 17-3-15.
*/
public class MappedIOTest {
//输入值的数量
private static int numOfInts = 4000000;
//测试读写值的数量大小
private static int numOfUbuffInts = 200000; private abstract static class Tester{
private String name;
public Tester(String name){
this.name = name;
} //测试计时
public void runTest(){
System.out.println(name + ": ");
try {
long start = System.nanoTime();
test();
long runtime = System.nanoTime() - start;
//输出test()运行时间,来判定操作时间大小
System.out.format("%.2f\n",runtime/1.0e9);
}catch (IOException e){
throw new RuntimeException(e);
}
} public abstract void test() throws IOException;
} private static Tester[] tests = {
//直接写入数据
new Tester("Stream Write") {
@Override
public void test() throws IOException {
DataOutputStream dos = new DataOutputStream(
new BufferedOutputStream(
new FileOutputStream(new File("temp.tmp"))));
for (int i = 0; i < numOfInts; i ++){
dos.writeInt(i);
}
dos.close();
}
},
//使用MappedByteBuffer进行写文件操作
new Tester("Mapped Write") {
@Override
public void test() throws IOException {
FileChannel fc = new RandomAccessFile("temp.tmp","rw").getChannel();
//fc.size()返回的是以byte为单位的数量值。
IntBuffer ib = fc.map(FileChannel.MapMode.READ_WRITE,0,fc.size()).asIntBuffer();
for(int i =0 ; i < numOfInts ; i ++){
try {
ib.put(i);
}catch (Exception e){
System.out.println(i);
}
}
fc.close();
}
},
//直接读数据
new Tester("Stream Read") {
@Override
public void test() throws IOException {
DataInputStream dis = new DataInputStream(
new BufferedInputStream(new FileInputStream("temp.tmp")));
for (int i = 0 ; i < numOfInts ; i ++){
dis.readInt();
}
dis.close();
}
},
//使用MappedByteBuffer进行读文件操作
new Tester("Mapped Read") {
@Override
public void test() throws IOException {
FileChannel fc = new FileInputStream(new File("temp.tmp")).getChannel();
IntBuffer ib = fc.map(FileChannel.MapMode.READ_ONLY,0,fc.size()).asIntBuffer();
while (ib.hasRemaining()){
ib.get();
}
fc.close();
}
},
//直接进行读/写操作
new Tester("Stream Read/Write") {
@Override
public void test() throws IOException {
RandomAccessFile raf = new RandomAccessFile(new File("temp.tmp"),"rw");
//对数据进行进行错位,以便同时进行读写操作
raf.writeInt(1);
for (int i = 0 ; i < numOfUbuffInts ; i ++){
//之所以减4的原因是raf.length()返回以byte为单位的空间大小,而1 (int) = 4 (byte),因此需要减4
raf.seek(raf.length() - 4);
raf.writeInt(raf.readInt());
}
raf.close();
}
},
//使用MappedByteBuffer进行读/写操作
new Tester("Mapped Read/Write") {
@Override
public void test() throws IOException {
FileChannel fc = new RandomAccessFile(new File("temp.tmp"),"rw").getChannel();
IntBuffer ib = fc.map(FileChannel.MapMode.READ_WRITE,0,fc.size()).asIntBuffer();
ib.put(0);
for (int i = 1 ; i < numOfUbuffInts ; i ++){
//对数据进行进行错位,以便同时进行读写操作
ib.put(ib.get(i - 1));
}
fc.close();
}
}
}; public static void main(String[] args) {
//进行测试
for (Tester tester : tests){
tester.runTest();
}
}
}

以下是运行结果:

  

java利用“映射文件访问”(MapperByteBuffer)处理文件与单纯利用Buffer来处理文件的快慢比较的更多相关文章

  1. Linux中ls -l(ll)返回结果中的文件访问权限-rw-r--rw-

    linux文件访问权限(像rw-r--rw-是什么意思)   Linux的文件访问权限分为 读.写.执行三种 r:可读(4) w:可写(2)对目录来说则可新建文件 x:可执行(1)对目录来说则可进入该 ...

  2. 使用Java内存映射(Memory-Mapped Files)处理大文件

    >>NIO中的内存映射 (1)什么是内存映射文件内存映射文件,是由一个文件到一块内存的映射,可以理解为将一个文件映射到进程地址,然后可以通过操作内存来访问文件数据.说白了就是使用虚拟内存将 ...

  3. java内存映射文件

    内存映射文件能够让我们创建和修改大文件(大到内存无法读入得文件),对于内存映射文件,我们可以认为是文件已经全部被读入到内存当中,然后当成一个大的数字来访问,简化修改文件的代码. 1.directBuf ...

  4. java 编程基础:注解(Annotation Processing Tool)注解处理器 利用注解解读类属性生成XML文件

    APT的介绍: APT(Annotation Processing Tool)是一种注解处理工具,它对源代码文件进行检测,并找出源文件所包含的注解信息,然后针对注解信息进行额外的处理. 使用APT工具 ...

  5. 无废话Android之android下junit测试框架配置、保存文件到手机内存、android下文件访问的权限、保存文件到SD卡、获取SD卡大小、使用SharedPreferences进行数据存储、使用Pull解析器操作XML文件、android下操作sqlite数据库和事务(2)

    1.android下junit测试框架配置 单元测试需要在手机中进行安装测试 (1).在清单文件中manifest节点下配置如下节点 <instrumentation android:name= ...

  6. 全面解决.Net与Java互通时的RSA加解密问题,使用PEM格式的密钥文件

    作者: zyl910 一.缘由 RSA是一种常用的非对称加密算法.所以有时需要在不用编程语言中分别使用RSA的加密.解密.例如用Java做后台服务端,用C#开发桌面的客户端软件时. 由于 .Net.J ...

  7. CDN加速静态文件访问

    CDN加速静态文件访问 全局调度 缓存技术 内容分发 带宽优化 CDN是Content Delivery Network的缩写,意思是内容分发网络.CDN的作用是把用户需要的内容分发到离用户近的地方, ...

  8. [apue] linux 文件访问权限那些事儿

    前言 说到 linux 上的文件权限,其实我们在说两个实体,一是文件,二是进程.一个进程能不能访问一个文件,其实由三部分内容决定: 文件的所有者.所在的组: 文件对所有者.组用户.其它用户设置的权限访 ...

  9. Android开发学习---android下的数据持久化,保存数据到rom文件,android_data目录下文件访问的权限控制

    一.需求 做一个类似QQ登录似的app,将数据写到ROM文件里,并对数据进行回显. 二.截图 登录界面: 文件浏览器,查看文件的保存路径:/data/data/com.amos.datasave/fi ...

随机推荐

  1. doubango(3)--协议栈的启动过程

    协议栈启动的上层接口 对于Doubango中得sip协议栈,是通过SipStack类粘合上层代码与底层代码的,该类定义在SipStack.h中,实现在SipStack.cxx中.当构造好一个SipSt ...

  2. SimpleDateFormat解析的时候字符串过长问题

    竟然不会报错: try { SimpleDateFormat dateFormatFrom = new SimpleDateFormat("yyyyMMddHHmmss"); St ...

  3. 无法删除MySql数据库,报错1010 error dropping

    环境:MySQL.Navicat 8 操作:Drop database testDB 报错:1010 error dropping database 解决方法:          ps -ef | g ...

  4. Spring 4 MVC+Hibernate 4+MySQL+Maven使用注解集成实例

    Spring 4 MVC+Hibernate 4+MySQL+Maven使用注解集成实例 转自:通过注解的方式集成Spring 4 MVC+Hibernate 4+MySQL+Maven,开发项目样例 ...

  5. BZOJ 1497: [NOI2006]最大获利(最大权闭合子图)

    1497: [NOI2006]最大获利 Time Limit: 5 Sec  Memory Limit: 64 MB Description 新的技术正冲击着手机通讯市场,对于各大运营商来说,这既是机 ...

  6. JavaScript 语法

    一.JavaScript简介 1.JavaScript是个什么东西? 它是个脚本语言,需要有宿主文件,它的宿主文件是HTML文件. 2.它与Java什么关系? 没有什么直接的联系,Java是Sun公司 ...

  7. jquery mobile多页面跳转等,data-ajax="false" 问题,

    当我们的网站引用了jquery mobile的js后,点击页面的链接,你会发现页面无法跳转,因为jquery mobile默认是采用ajax方式来加载网站的,如果你需要跳到另一个页面,需要在a标签加上 ...

  8. iOS8中 UITableView section 分区头部视图不显示

    最近自己使用了UITableView写了一个通讯录,但是在编写过程还算顺利,但是后来测试的时候,发现在iOS8中TableView的分区头不能正常显示,使用 - (NSString *)tableVi ...

  9. JS - What does `void 0` mean?

    语法 void expression // or void(expression) MDN的描述 能向期望一个表达式的值是 undefined 的地方插入会产生副作用的表达式.也就是为了避免产生某种副 ...

  10. javascript小测试

     测试地址:http://toys.usvsth3m.com/javascript-under-pressure/ 在群里看到测试网站做着玩,希望你能过关,不能,且看下面答案(为了过关,不惜不够严谨) ...