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

 

参考:

无格式输入流 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( )来查询锁的类型(共享还是独占)。