zoukankan      html  css  js  c++  java
  • java nio 之MappedByteBuffer

    其实掌握MappedByteBuffer并不难,只要记住“三方三法三特性”(我自己总结的,呵呵~~不要扔鸡蛋哦。。。)这句话就可以轻松搞定!MappedByteBuffer 只是一种特殊的 ByteBuffer ,即是ByteBuffer的子类。 MappedByteBuffer 将文件直接映射到内存(这里的内存指的是虚拟内存,并不是物理内存,后面说证明这一点)。通常,可以映射整个文件,如果文件比较大的话可以分段进行映射,只要指定文件的那个部分就可以。而且,与ByteBuffer十分类似,没有构造函数(你不可new MappedByteBuffer()来构造一个MappedByteBuffer),我们可以通过 java.nio.channels.FileChannel 的 map() 方法来获取 MappedByteBuffer 。其实说的通俗一点就是Map把文件的内容被映像到计算机虚拟内存的一块区域,这样就可以直接操作内存当中的数据而无需操作的时候每次都通过I/O去物理硬盘读取文件,所以效率上有很大的提升!

    三种方式:

                  FileChannel提供了map方法来把文件影射为内存映像文件: MappedByteBuffer map(int mode,long position,long size); 可以把文件的从position开始的size大小的区域映射为内存映像文件,mode指出了 可访问该内存映像文件的方式:READ_ONLY,READ_WRITE,PRIVATE.                     

    a. READ_ONLY,(只读): 试图修改得到的缓冲区将导致抛出 ReadOnlyBufferException.(MapMode.READ_ONLY)

           b. READ_WRITE(读/写): 对得到的缓冲区的更改最终将传播到文件;该更改对映射到同一文件的其他程序不一定是可见的。 (MapMode.READ_WRITE)

            c. PRIVATE(专用): 对得到的缓冲区的更改不会传播到文件,并且该更改对映射到同一文件的其他程序也不是可见的;相反,会创建缓冲区已修改部分的专用副本。 (MapMode.PRIVATE)

     

    三个方法:

    a. fore();缓冲区是READ_WRITE模式下,此方法对缓冲区内容的修改强行写入文件

    b. load()将缓冲区的内容载入内存,并返回该缓冲区的引用

    c. isLoaded()如果缓冲区的内容在物理内存中,则返回真,否则返回假

    三个特性:

    调用信道的map()方法后,即可将文件的某一部分或全部映射到内存中,映射内存缓冲区是个直接缓冲区,继承自ByteBuffer,但相对于ByteBuffer,它有更多的优点:

    a. 读取快

    b. 写入快

    c. 随时随地写入

           口说无凭,俗话说的好,是金子是银子拿来炼一炼就知道(也不知道有没有这么一句俗话,反正用到这还合适,就这么凑合吧,大家扔鸡蛋~~~)!

    1 MappedByteBuffer的读取/写入文件和普通I/O流的对比

    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.nio.ByteBuffer;
    import java.nio.CharBuffer;
    import java.nio.MappedByteBuffer;
    import java.nio.channels.FileChannel;
    import java.nio.charset.Charset;
    import java.nio.charset.CharsetDecoder;
     
     
    public class MapMemeryBuffer {
           public static void main(String[] args) throws Exception {
                  ByteBuffer byteBuf = ByteBuffer.allocate(1024 * 14 * 1024);
                  byte[] bbb = new byte[14 * 1024 * 1024];
                  FileInputStream fis = new FileInputStream("d://test");
                  FileOutputStream fos = new FileOutputStream("d://outFile.txt");
                  FileChannel fc = fis.getChannel();
                 
                  long timeStar = System.currentTimeMillis();//得到当前的时间
     
                  fc.read(byteBuf);// 1 读取
     
                  long timeEnd = System.currentTimeMillis();//得到当前的时间
     
                  System.out.println("Read time :" + (timeEnd - timeStar) + "ms");
                  timeStar = System.currentTimeMillis();
     
                  fos.write(bbb);// 2 写入
     
                  timeEnd = System.currentTimeMillis();
                  System.out.println("Write time :" + (timeEnd - timeStar) + "ms");
                  fos.flush();
                  fc.close();
                  fis.close();
           }
    }


    输出结果:

    Read time :1874ms

    Write time :360ms

    把上面的程序的1换成MappedByteBuffer mbb = fc.map(FileChannel.MapMode.READ_ONLY, 0, fileLength);

    2换成mbb.flip();

    输出结果:

    Read ByteBuf take time :16ms

    Write ByteBuf take time :0ms

    可见普通I/O和MappedByteBuffer是没法比的。另外在写入的时候花了0ms说明Map写入机制是根据你的更改量来决定,就是只保存修改部分的!

  • 相关阅读:
    Net Remoting(应用程序域)
    C# 方便的复制/比较物件内数据的方法(Object Copy / Compare)
    c# 序列化
    Windows Phone 7 开发日志(初试一、随便研究)
    关于Windows Phone 7推广策略的失误
    vb 托盘图标
    vb code中调用exe文件,当关闭的时候直接关闭文件.
    调用INI文件
    使用SQL的JOB调用DTS定制任务!
    给Word设置目录
  • 原文地址:https://www.cnblogs.com/pekkle/p/6568824.html
Copyright © 2011-2022 走看看