Java基础增强 : 新I/O中内存映射文件

原创 2013年12月02日 15:55:18

 ---------------------- ASP.Net+Android+IOS开发.Net培训、期待与您交流! ----------------------

                                                                              

               大多数操作系统都支持利用虚拟内存实现来将一个文件或者一个文件的一部分“映射”到内存中。                                               

      在java中这种操作相当简单,相对带缓冲区的的顺序输入流要稍快一点,而比RandomAccessFile要快很多。具体做法如下。

       首先,从文件中获得一个通道,通道适用于磁盘文件的一种抽象,它使得我们可以访问诸如内存映射、文件加锁机制以及文件件快速数据传输等操作系统系统特征。我们可以通过调用getChannel方法来获得通道。

               FileInputStream inputStream = new FileInputStream(fileName);

               FileChannel channel = inputStream.getChannel();

      然后,通过调用FileChannel类的map方法从这个通道中获得一个MappedByteBuffer,可以指定你想要映射的文件区域与映射模式,有三种模式可以 选择:

            FileChannel.MapMode.READ_ONLY : 所产生的缓冲区是可读的

            FileChannel.MapMode.READ_WRITE : 所产生的缓冲区可读可写

            FileChannel.MapMode.PRIVATE: 所产生的缓冲区是可写的,但是任读写改都不会对源文件造成更改             

     这里我就写个程序来看看FileInputStream、BufferedInputStrream、RandomAccessFile、MappedFile速度差异

      首先用到了CRC32这个类,在java.util.zip包下,该类用于计算文件的32为的循环冗余校验和,这个数值经常用来判断一个文件是否已经损坏。

      用法如下:

                            CRC32 crc = new CRC32();

                            while(hashMoreBytes){

                                   crc.update(nextByte);

                               }

                             long result = crc.getValue();

                                           

      一般大小的文件没必要用到内存映射文件,我选用的是jre下的rt.jar,大约49MB。

       好了,我的源程序如下:

public class MemeryMappedFile {
	
	
	public static long checkSumMappedFile(String fileName)throws IOException{
		FileInputStream fis = new FileInputStream(fileName);
		FileChannel channel = fis.getChannel();
		CRC32 crc = new CRC32();
		int length = (int) channel.size();
		MappedByteBuffer buffer = channel.map(FileChannel.MapMode.READ_ONLY, 0, length);
		for(int i=0; i<length; i++){
			int c = buffer.get(i);
			crc.update(c);
		}
		return crc.getValue();
	}
	
	public static long checkSumInputStream(String fileName)throws IOException{
		InputStream inputStream = new FileInputStream(fileName);
		CRC32 crc = new CRC32();
		int c;
		while((c = inputStream.read()) != -1){
			crc.update(c);
		}
		return crc.getValue();
	}
	
	public static long checkSumBufferedInputStream(String fileName)throws IOException{
		InputStream inputStream = new BufferedInputStream(new FileInputStream(fileName));
		CRC32 crc = new CRC32();
		int c;
		while((c = inputStream.read()) != -1){
			crc.update(c);
		}
		return crc.getValue();
	}
	
	public static long checkSumRandomAccessFile(String fileName)throws IOException{
		RandomAccessFile randomFile = new RandomAccessFile(fileName,"r");
		long length = randomFile.length();
		CRC32 crc = new CRC32();
		for(long i=0; i<length; i++){
			randomFile.seek(i);
			int c = randomFile.readByte();
			crc.update(c);
		}
		
		
		return crc.getValue();
	}
	
	
	
	public static void main(String [] args)throws Exception{
	   String fileName = "C:\\Program Files\\Java\\jre7\\lib\\rt.jar";
	   long start,end;
	   long value;
	   start = System.currentTimeMillis();
	   value = checkSumMappedFile(fileName);
	   end = System.currentTimeMillis();
	   System.out.println("内存映射文件 CRC32  校验结果  :" +  value);
	   System.out.println("内存映射文件  耗时 : " + (end - start) + "毫秒");
	   
	   start = System.currentTimeMillis();
	   value = checkSumInputStream(fileName);
	   end = System.currentTimeMillis();
	   System.out.println("InputStream CRC32  校验结果  :" +  value);
	   System.out.println("Inputstream 耗时 : " + (end - start) + "毫秒");
	   
	   
	   start = System.currentTimeMillis();
	   value = checkSumBufferedInputStream(fileName);
	   end = System.currentTimeMillis();
	   System.out.println("BufferedInputStream CRC32  校验结果  :" +  value);
	   System.out.println("BufferedInputStream 耗时 : " + (end - start) + "毫秒");
	   
	   
	   start = System.currentTimeMillis();
	   value = checkSumRandomAccessFile(fileName);
	   end = System.currentTimeMillis();
	   System.out.println("RandomAccessFile CRC32  校验结果  :" +  value);
	   System.out.println("RandomAccessFile 耗时 : " + (end - start) + "毫秒");
	   
	}

}


在我的电脑上运行的结果为:

                                                内存映射文件 CRC32  校验结果  :1450405243
                                                内存映射文件  耗时 : 1516毫秒
                                                InputStream CRC32  校验结果  :1450405243
                                                Inputstream 耗时 : 52781毫秒
                                                BufferedInputStream CRC32  校验结果  :1450405243
                                                BufferedInputStream 耗时 : 1672毫秒
                                                RandomAccessFile CRC32  校验结果  :1450405243
                                                RandomAccessFile 耗时 : 79047毫秒

                                       

                                           -----------------------------------------------------------------------------

                                                     方    法                                                    耗    时(毫秒)

                                           -----------------------------------------------------------------------------

                                                   普通输入流                                                   52781

                                                   带缓冲的输入流                                           1672

                                                   随机访问文件                                               79047

                                                   内存映射文件                                               1516

                                           ------------------------------------------------------------------------------

    

                               效果还是很明显的: 内存映射文件最快,比带缓冲区的输入流稍快,但是比普通的输入流和随机访问文件快很多的,尤其是比随机访问文件快了50多倍。

                                                          

 

 

 

内存映射文件-Java I/O系统

性能
  • Asmots
  • Asmots
  • 2014年11月13日 10:13
  • 413

深入理解JavaI/O流

其实我个人觉得,javaI/O流是一种比较乏味的事情。因为看不到明显的运行效果,但是输入输出程序都需要用到I/O操作即:允许程序读取外部数据、用户输入数据,使用输出机制允许程序记录运行状态,将数据仅处...
  • blueZhangFun
  • blueZhangFun
  • 2015年07月27日 11:59
  • 1458

Java I/O 流详解

原文地址: http://blog.csdn.net/jiangwei0910410003/article/details/22376895 摘要: Java 流在处理上分为字符流和...
  • jason_rainbow
  • jason_rainbow
  • 2016年03月17日 11:40
  • 439

java i/o操作

1. I/O介绍:中I/O操作主要是指使用Java进行输入,输出操作. Java所有的I/O机制都是基于数据流进行输入输出,这些数据流表示了字符或者字节数据的流动序列。Java.io是大多数面向数据流...
  • jiachangbin1989
  • jiachangbin1989
  • 2016年04月19日 16:07
  • 1047

内存映射文件 I/O

内存映射文件 I/O 是一种读和写文件数据的方法,它可以比常规的基于流或者基于通道的 I/O 快得多。 内存映射文件 I/O 是通过使文件中的数据神奇般地出现为内存数组的内容来完成的。这其初听起来...
  • yhang
  • yhang
  • 2004年07月19日 15:24
  • 1397

《JAVA I/O最详解》

刚开始学Java时候,一直搞不懂Java里面的io关系,在网上找了很多大多都是给个结构图草草描述也看的不是很懂。而且没有结合到java7 的最新技术,所以自己结合API来整理一下,有错的话请指正,...
  • self_realian
  • self_realian
  • 2016年07月19日 17:31
  • 1923

深入理解 java I/O

Java 的 I/O 类库的基本架构 I/O 问题是任何编程语言都无法回避的问题,可以说 I/O 问题是整个人机交互的核心问题,因为 I/O 是机器获取和交换信息的主要渠道。在当今这个数据大爆炸...
  • Mr_Tim
  • Mr_Tim
  • 2016年04月06日 11:42
  • 872

I/O 和 内存映射文件

内存映射文件最快,其次是缓冲器和通道(nio),最后是一般的io操作 旧的I/O:java.io.* 输入流(字节流,字符流)(部分)                       ...
  • fuckluy
  • fuckluy
  • 2016年02月14日 14:23
  • 228

10029--- I/O 基础之缓冲区

原文 I/O 基础 缓冲区操作 缓冲区以及缓冲区是如何工作,是所有I/O的基础。“输入/输出”就是把数据移进或移出缓冲区。 进程执行I/O操作,就是向操作系统发出请求,让它要么把缓冲区的数据排干(写...
  • xxxcyzyy
  • xxxcyzyy
  • 2016年01月27日 17:21
  • 190

关于Java中的I/O流的总结

1. java中I/O的相关概念介绍:Java中的读写操作基本分为两种形式:字节流(byte、8位、一般以Stream结尾)、字符流(char、16位、一般以Reader、Writer结尾);其中字符...
  • update_java
  • update_java
  • 2015年04月25日 17:15
  • 982
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Java基础增强 : 新I/O中内存映射文件
举报原因:
原因补充:

(最多只允许输入30个字)