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系统(6)-内存映射文件

在前面的博文中关于RandomAccessFile类对超大文件的处理方式进行了学习,随机访问是独立的,支持读写的,而且它最大的特征是可以访问文件中任意一个位置。在本篇博文中,认识一个基于NIO的对于大...

黑马程序员_O‘Reilly java nio学习笔记之通道_内存映射文件&&Channel-to-Channel 传输

---------------------- android培训、java培训、期待与您交流! ---------------------- 4.内存映射文件     新的File...

内存映射文件

  • 2015年04月11日 11:19
  • 5.75MB
  • 下载

为何要在Java中使用内存映射文件(Memory Mapped File)或者MappedByteBuffer

尽管从JDK 1.4版本开始,Java内存映射文件(Memory Mapped Files)就已经在java.nio包中,但它对很多程序开发者来说仍然是一个相当新的概念。引入NIO后,Java IO已...

Java NIO笔记之内存映射文件

大致的原理图如下: FileChannel提供了一个map()的方法,该方法可以在一个打开的文件和一个特殊类型的ByteBuffer之间建立一个虚拟内存映射。在FileChannel上调用map...
  • zxdfc
  • zxdfc
  • 2017年03月02日 00:00
  • 262

Java 中使用内存映射文件需要考虑的 10 个问题

Java中的内存映射IO和内存映射文件是什么?内存映射文件非常特别,它允许Java程序直接从内存中读取文件内容,通过将整个或部分文件映射到内存,由操作系统来处理加载请求和写入文件,应用只需要和内存打交...

Java NIO 内存映射文件实现进程间通信

一看到 Java NIO 的内存映射文件(MappedByteBuffer),让我立即就联想到 Windows 系统的内存映射文件和Linux系统上的共享内存技术。Windows 系统的内存映射文件能...

java流的性能优化2-内存映射文件

NIO提供了一种将文件映射到

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

转载自:http://www.360doc.com/content/13/0502/23/7669533_282552666.shtml  JAVA类库中的NIO包相对于IO 包来说有一个...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Java基础增强 : 新I/O中内存映射文件
举报原因:
原因补充:

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