Java NIO教程 MappedByteBuffer

首先从大体上讲一下MappedByteBuffer究竟是什么。从继承结构上来讲,MappedByteBuffer继承自ByteBuffer,所以ByteBuffer有的能力它全有;像变动position和limit指针啦、包装一个其他种类Buffer的视图啦,都可以。“MappedByteBuffer”为何而来?吾辈心中亦有惑(熊猫人之谜的梗)用一个字来概括就是

为什么?因为它使用direct buffer的方式读写文件内容,这种方式的学名叫做内存映射。这种方式直接调用系统底层的缓存,没有JVM和系统之间的复制操作,所以效率大大的提高了。而且由于它这么快,还可以用它来在进程(或线程)间传递消息,基本上能达到和“共享内存页”相同的作用,只不过它是依托实体文件来运行的。

而且它还有另一种能力。就是它可以让我们读写那些因为太大而不能放进内存中的文件。有了它,我们就可以假定整个文件都放在内存中(实际上,大文件放在内存和虚拟内存中),基本上都可以将它当作一个特别大的数组来访问,这样极大的简化了对于大文件的修改等操作。

下面我们开始介绍它的用法了

FileChannel提供了map方法来把文件映射为MappedByteBuffer: MappedByteBuffer map(int mode,long position,long size); 可以把文件的从position开始的size大小的区域映射为MappedByteBuffer,mode指出了可访问该内存映像文件的方式,共有三种,分别为:
MapMode.READ_ONLY(只读): 试图修改得到的缓冲区将导致抛出 ReadOnlyBufferException。
MapMode.READ_WRITE(读/写): 对得到的缓冲区的更改最终将写入文件;但该更改对映射到同一文件的其他程序不一定是可见的(无处不在的“一致性问题”又出现了)。
MapMode.PRIVATE(专用): 可读可写,但是修改的内容不会写入文件,只是buffer自身的改变,这种能力称之为”copy on write”

再简单的说一下,MappedByteBuffer较之ByteBuffer新增的三个方法

  • fore()缓冲区是READ_WRITE模式下,此方法对缓冲区内容的修改强行写入文件
  • load()将缓冲区的内容载入内存,并返回该缓冲区的引用
  • isLoaded()如果缓冲区的内容在物理内存中,则返回真,否则返回假.
  • import java.io.DataInputStream;
    import java.io.DataOutputStream;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.nio.MappedByteBuffer;
    import java.nio.channels.FileChannel;
    import java.nio.file.Paths;
    import java.nio.file.StandardOpenOption;
    
    public class TestMappedByteBuffer {
        private static int length = 0x2FFFFFFF;//1G
        private abstract static class Tester {
            private String name;
            public Tester(String name) {
                this.name = name;
            }
            public void runTest() {
                System.out.print(name + ": ");
                long start = System.currentTimeMillis();
                test();
                System.out.println(System.currentTimeMillis()-start+" ms");
            }
            public abstract void test();
        }
        private static Tester[] testers = {
            new Tester("Stream RW") {
                public void test() {
                    try (FileInputStream fis = new FileInputStream(
                            "src/a.txt");
                            DataInputStream dis = new DataInputStream(fis);
                            FileOutputStream fos = new FileOutputStream(
                                    "src/a.txt");
                            DataOutputStream dos = new DataOutputStream(fos);) {
                        
                        byte b = (byte)0;
                        for(int i=0;i<length;i++) {
                            dos.writeByte(b);
                            dos.flush();
                        }                   
                        while (dis.read()!= -1) {
                        }
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            },
            new Tester("Mapped RW") {
                public void test() {
                    try (FileChannel channel = FileChannel.open(Paths.get("src/b.txt"),
                            StandardOpenOption.READ, StandardOpenOption.WRITE);) {
                        MappedByteBuffer mapBuffer = channel.map(FileChannel.MapMode.READ_WRITE, 0, length);
                        for(int i=0;i<length;i++) {
                            mapBuffer.put((byte)0);
                        }
                        mapBuffer.flip();
                        while(mapBuffer.hasRemaining()) {
                            mapBuffer.get();
                        }
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            },
            new Tester("Mapped PRIVATE") {
                public void test() {
                    try (FileChannel channel = FileChannel.open(Paths.get("src/c.txt"),
                            StandardOpenOption.READ, StandardOpenOption.WRITE);) {
                        MappedByteBuffer mapBuffer = channel.map(FileChannel.MapMode.PRIVATE, 0, length);
                        for(int i=0;i<length;i++) {
                            mapBuffer.put((byte)0);
                        }
                        mapBuffer.flip();
                        while(mapBuffer.hasRemaining()) {
                            mapBuffer.get();
                        }
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        };
        public static void main(String[] args) {
            for(Tester tester:testers) {
                tester.runTest();
            }
        }
    }

     

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值