zoukankan      html  css  js  c++  java
  • 转:JAVA内存映射文件

    解释:将文件的一段区域映射到内存中,比传统的文件处理速度要快很多

    参考:

    无格式输入流 110秒

    缓冲输入流     9.9秒

    随机存取文件  162秒

    内存映射文件   7.2秒

    例子

    Java代码
    1. package twelve;  
    2.   
    3. import java.io.BufferedInputStream;  
    4. import java.io.FileInputStream;  
    5. import java.io.FileNotFoundException;  
    6. import java.io.IOException;  
    7. import java.io.InputStream;  
    8. import java.io.RandomAccessFile;  
    9. import java.nio.MappedByteBuffer;  
    10. import java.nio.channels.FileChannel;  
    11. import java.util.zip.CRC32;  
    12.   
    13. /** 
    14.   @Title NIOTTest.java 
    15.   @description  TODO 
    16.   @author qinpeng 
    17.   @date Aug 25, 2009 10:23:26 PM 
    18.  */  
    19. public class NIOTTest {  
    20.       
    21.     public static void main(String[] args) {  
    22.           
    23.         String fileName = "d:\\IOTest.pdf";  
    24.           
    25.         System.out.println("inputStream");  
    26.         long start = System.currentTimeMillis();  
    27.         long crcValue = checksumInputStreanm(fileName);  
    28.         long end = System.currentTimeMillis();  
    29.         System.out.println(Long.toHexString(crcValue));  
    30.         System.out.println((end - start)+"耗时");  
    31.           
    32.         System.out.println("BufferedinputStream");  
    33.         start = System.currentTimeMillis();  
    34.         crcValue = checksumInputStreanm(fileName);  
    35.         end = System.currentTimeMillis();  
    36.         System.out.println(Long.toHexString(crcValue));  
    37.         System.out.println((end - start)+"耗时");  
    38.           
    39.         System.out.println("RandomAccessFileinputStream");  
    40.         start = System.currentTimeMillis();  
    41.         crcValue = checksumInputStreanm(fileName);  
    42.         end = System.currentTimeMillis();  
    43.         System.out.println(Long.toHexString(crcValue));  
    44.         System.out.println((end - start)+"耗时");  
    45.           
    46.         System.out.println(" MappedFile inputStream");  
    47.         start = System.currentTimeMillis();  
    48.         crcValue = checksumInputStreanm(fileName);  
    49.         end = System.currentTimeMillis();  
    50.         System.out.println(Long.toHexString(crcValue));  
    51.         System.out.println((end - start)+"耗时");  
    52.     }  
    53.       
    54.       
    55.       
    56.     public static long checksumInputStreanm(String fileName){  
    57.         CRC32 crc = new CRC32();  
    58.         try {  
    59.             InputStream in = new FileInputStream(fileName);  
    60.             int c;  
    61.             while((c=in.read())!=-1){  
    62.                 crc.update(c);  
    63.             }  
    64.         } catch (FileNotFoundException e) {  
    65.             e.printStackTrace();  
    66.             System.err.print("NIOTTest--checksumInputStreanm--new FileInputStream is not found");  
    67.         } catch(IOException ioe){  
    68.             ioe.printStackTrace();  
    69.             System.err.print("NIOTTest--checksumInputStreanm--new FileInputStream'read append IOException");  
    70.         }  
    71.         return crc.getValue();  
    72.     }  
    73.       
    74.     public static long checksumBufferedInputStream(String fileName){  
    75.         CRC32 crc = new CRC32();  
    76.         try {  
    77.             InputStream in = new BufferedInputStream(new FileInputStream(fileName));  
    78.             int c;  
    79.             while((c=in.read())!=-1){  
    80.                 crc.update(c);  
    81.             }  
    82.         } catch (FileNotFoundException e) {  
    83.             e.printStackTrace();  
    84.             System.err.print("NIOTTest--checksumBufferedInputStream--new FileInputStream is not found");  
    85.         } catch(IOException ioe){  
    86.             ioe.printStackTrace();  
    87.             System.err.print("NIOTTest--checksumBufferedInputStream--new FileInputStream'read append IOException");  
    88.         }  
    89.         return crc.getValue();  
    90.     }  
    91.       
    92.       
    93.     public static long checksumRondomAccessFileInputStream(String fileName){  
    94.         CRC32 crc = new CRC32();  
    95.         try {  
    96.             RandomAccessFile file = new RandomAccessFile(fileName,"r");  
    97.             int c;  
    98.             while((c=file.read())!=-1){  
    99.                 crc.update(c);  
    100.             }  
    101.         } catch (FileNotFoundException e) {  
    102.             e.printStackTrace();  
    103.             System.err.print("NIOTTest--checksumRondomAccessFileInputStream--new FileInputStream is not found");  
    104.         } catch(IOException ioe){  
    105.             ioe.printStackTrace();  
    106.             System.err.print("NIOTTest--checksumRondomAccessFileInputStream--new FileInputStream'read append IOException");  
    107.         }  
    108.         return crc.getValue();  
    109.     }  
    110.   
    111.     public static long checksumMappedFile(String fileName){  
    112.         CRC32 crc = new CRC32();  
    113.         try {  
    114.             FileInputStream in = new FileInputStream(fileName);  
    115.             FileChannel channel = in.getChannel();  
    116.             int length = (int) channel.size();  
    117.             MappedByteBuffer buffer = channel.map(FileChannel.MapMode.READ_ONLY, 0, length);  
    118.               
    119.             for(int p = 0;p<length;p++){  
    120.                 int c = buffer.getInt(p);  
    121.                 crc.update(c);  
    122.             }  
    123.         } catch (FileNotFoundException e) {  
    124.             e.printStackTrace();  
    125.             System.err.print("NIOTTest--checksumRondomAccessFileInputStream--new FileInputStream is not found");  
    126.         } catch(IOException ioe){  
    127.             ioe.printStackTrace();  
    128.             System.err.print("NIOTTest--checksumRondomAccessFileInputStream--new FileInputStream'read append IOException");  
    129.         }  
    130.         return crc.getValue();  
    131.     }  
    132.       
    133.       

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

    内存映射文件(memory-mapped file)能让你创建和修改那些大到无法读入内存的文件。有了内存映射文件,你就可以认为文件已经全部读进了内存,然后把它当成一个非常大的数组来访问了。这种解决思路能大大简化修改文件的代码。下面就是一个简单的例子:

    代码
    1. import java.io.*;   
    2. import java.nio.*;   
    3. import java.nio.channels.*;   
    4. public class LargeMappedFiles {   
    5.   static int length = 0x8FFFFFF; // 128 Mb   
    6.   public static void main(String[] args) throws Exception {   
    7.        MappedByteBuffer out =    
    8.       new RandomAccessFile("test.dat", "rw").getChannel()   
    9.          .map(FileChannel.MapMode.READ_WRITE, 0, length);   
    10.     for(int i = 0; i < length; i++)   
    11.          out.put((byte)'x');   
    12.        System.out.println("Finished writing");   
    13.     for(int i = length/2; i < length/2 + 6; i++)   
    14.          System.out.print((char)out.get(i));   
    15.      }   
    16. }  

    为了能以读写的方式打开文件,我们从RandomAccessFile入手。拿到channel之后,我们用map( )方法生成了一个MappedByteBuffer。这是一种特殊的"direct buffer"。注意,你必须指明,它是从文件的哪个位置开始映射的,映射的范围又有多大;也就是说,它还可以映射一个大文件的某个小片断。
    MappedByteBuffer是ByteBuffer的派生类,因此它具备了ByteBuffer的所有方法。这里只简单地演示了一下put( )和get( )方法,除此之外,你还可以使用asCharBuffer( )之类的方法。

    上述例程创建了一个128MB的文件,或许这已经超出OS的允许范围了。文件的访问好像只是一瞬间的事,这是因为,真正调入内存的只是其中的一小部分,其余部分则被放在交换文件上。这样你就可以很方便地修改超大型的文件了(最大可以到2 GB)。
    注意,Java是调用操作系统的"文件映射机制(file-mapping facility)"来提升性能的。

    由于Java的文件锁是直接映射操作系统的锁机制的,因此其它进程也能看到文件锁。

    虽然你可以用wrap( ) 直接把char数组转换成CharBuffer,但实际上它还是一个ByteBuffer,而CharBuffer只是它的view。由此可知,我们操控的对象永远都是ByteBuffer,因为只有它才能往channel里读写数据。

    一般来说,你是不会让两个进程去共享一个网络socket的。)tryLock( ) 是非阻塞的。它会试着去获取这个锁,但是如果得不到(其它进程已经以独占方式得到这个锁了),那它就直接返回。而lock( )是阻塞的。如果得不到锁,它会在一直处于阻塞状态,除非它得到了锁,或者你打断了调用它(即lock( )方法)的线程,或者关闭了它要lock( )的channel,否则它是不会返回的。最后用FileLock.release( )释放锁。

    还可以像这样锁住文件的某一部分

    tryLock(long position, long size, boolean shared)
    或者

    lock(long position, long size, boolean shared)
    这个方法能锁住文件的某个区域(size - position)。
    其中第三个参数表示锁能不能共享。
    虽然在修改文件的过程中,无参数的lock( )和tryLock( )方法的锁定范围会随文件大小的变化,带参数的方法却不行。如果你锁住了position到position+size这段范围,而文件的长度又增加了,那么position+size后面是不加锁的。而无参数的lock方法则会锁定整个文件,不管它变不变长。

    锁是独占的还是共享的,这要由操作系统来决定。如果操作系统不支持共享锁,而程序又申请了一个,那么它会返回一个独占锁。你可以用FileLock.isShared( )来查询锁的类型(共享还是独占)。

  • 相关阅读:
    5_4 编码重新总结
    5_9 ___2 mc函数
    5_9 代码分析 load_pic_pointers
    5_2 实现过程中
    5_4 calvc
    428 对于 mb_cmp_init函数中一些宏定义的展开 x264_encoder_open中
    Oracle数值处理函数
    JAVA常用注解
    Java随笔
    centos 7 上Hive2.1.1的安装与基本操作
  • 原文地址:https://www.cnblogs.com/phoebus0501/p/1897870.html
Copyright © 2011-2022 走看看