直接缓冲区实战

x33g5p2x  于2022-05-22 转载在 其他  
字(1.3k)|赞(0)|评价(0)|浏览(198)

一 在直接缓冲区对文件进行修改

1 需求

在直接缓冲区,使用 MappedByBuffer 修改文件内容。

2 代码

public static void test4() throws IOException {
    RandomAccessFile raf = new RandomAccessFile("G:\\abc.txt", "rw");
    FileChannel fileChannel = raf.getChannel();
    // mappedByteBuffer:代表了 abc.txt 在内存中的映射文件
    MappedByteBuffer mappedByteBuffer = fileChannel.map(FileChannel.MapMode.READ_WRITE, 0, raf.length());
    // 修改内存中的数据
    mappedByteBuffer.put(1, (byte) 'X');
    // 只需关心内存中的数据
    mappedByteBuffer.put(3, (byte) 'Y');
    raf.close();
}

3 测试

a 修改前文件内容
helloworld

b 修改后文件内容

hXlYoworld

4 说明

如果使用的是直接缓冲区,那么 JVM 在每次调用 I/O 操作之前或之后,都会尽量避免将缓冲区的内容复制到中间缓冲区(或从中间缓冲区中复制内容)。并且直接缓冲区是驻留在 JVM 之外的区域,因此无法受 Java 代码及 GC 的控制。此外,分配直接缓冲区时系统开销较大,因此,建议将直接缓冲区分配给那些持久的、经常重用的数据使用。

二 零拷贝

1 需求

使用零拷贝内存的方式,完成文件的复制

2 代码

// 在直接缓冲区中,将输入通道的数据直接转发给输出通道
public static void test4() throws IOException {
    long start = System.currentTimeMillis();
    FileChannel inChannel = FileChannel.open(Paths.get("g:\\navicat.chm"), StandardOpenOption.READ);
    FileChannel outChannel = FileChannel.open(Paths.get("g:\\navicat1.chm"), StandardOpenOption.WRITE, StandardOpenOption.READ, StandardOpenOption.CREATE);
    inChannel.transferTo(0, inChannel.size(), outChannel);
    /*
     也可以使用输出通道完成复制,即上条语句等价于以下写法:
     outChannel.transferFrom(inChannel, 0, inChannel.size());
    */
    inChannel.close();
    outChannel.close();
    long end = System.currentTimeMillis();
    System.out.println("复制操作消耗的时间(毫秒):" + (end - start));
}

3 测试

复制操作消耗的时间(毫秒):7

相关文章