笔记:I/O流-内存映射文件
Posted 追寻自由的路途
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了笔记:I/O流-内存映射文件相关的知识,希望对你有一定的参考价值。
内存映射文件时利用虚拟内存实现来将一个文件或者文件的一部分映射到内存中,然后整个文件就可以当作数组一样的访问,这个比传统的文件操作要快得多,Java 使用内存映射文件首先需要从文件中获取一个channel(通道),通道时磁盘文件的一个抽象,他使得我们可以访问诸如内存映射、文件加锁机制以及文件间快速数据传递等操作系统特性,然后通过调用 FileChannel 类的 map 方法从这个通道获取一个映射块(ByteBuffer),然后就可以读取/写入文件块内容,map 支持的模式有如下:
- FileChannel.MapMode.READ_ONLY:所产生的缓冲区是只读的,如果对只读的缓冲区进行写操作,将会导致 ReadonlyBufferException 异常
- FileChannel.MapMode.READ_WRITE:所产生的缓冲区是可写的,任何修改都会在某个时刻写回文件(写入不是及时的)
- FileChannel.MapMode.PRIVATE:所产生的缓冲区是可写的,但是任何修改对这个缓冲区来说都是私有的,不会传播到文件中
映射文件示例代码:
- 读取文件:
?????????Path filePath = Paths.get("D:\\我的游戏\\World of Warcraft\\Data\\data", "data.001");
?????????long startTime = System.currentTimeMillis(); //获取开始时间
????????try {
???????????????try (FileChannel channel = FileChannel.open(filePath, StandardOpenOption.READ)) {
???????????????????????int size = 40960;
???????????????????????long readByteSize = 0;
???????????????????????ByteBuffer byteBuffer = ByteBuffer.allocate(size);
???????????????????????int readCount;
????????????????????????do {
?????????????????????????????????readCount = channel.read(byteBuffer);
?????????????????????????????????byte[] readBytes = new byte[byteBuffer.limit()];
??????????????????????????????? // channel.read 后其 position 是 readCount,因此需要读取数据时,需要重置 position = 0
???????????????????????????????? byteBuffer.position(0);
?????????????????????????????????for(int i=0;i< readBytes.length;i++){
????????????????????????????????????????readBytes[i] = byteBuffer.get();
?????????????????????????????????}
?????????????????????????????????byteBuffer.clear();
??????????????????????????????? if (readCount != -1) {
???????????????????????????????????????readByteSize += readCount;
??????????????????????????????? ?}
??????????????????????????????? System.out.print("readCount +" + readCount + " readByteSize " + readByteSize + " ");
?????????????????????????} while (readCount != -1);
????????????????}
????????} catch (IOException ex) {
????????????????????????ex.printStackTrace();
?????? ?}
????????long endTime = System.currentTimeMillis(); //获取结束时间
????????System.out.println("程序运行时间: " + (endTime - startTime) + "ms");
? ?
- 写入文件(使用 RandomAccessFile 和 MappedByteBuffer):
????????????????Random random = new Random();
????????????????Path writeFilePath = Paths.get("d:\\channel.dat");
????????????????startTime = System.currentTimeMillis(); //获取开始时间
????????????????try {
????????????????????????byte[] buff = new byte[40960];
????????????????????????long position = 0;
????????????????????????long size = buff.length;
????????????????????????RandomAccessFile randomAccessFile = new RandomAccessFile(writeFilePath.toString(), "rw");
????????????????????????try (FileChannel outChannel = randomAccessFile.getChannel()) {
????????????????????????????????for (int i = 0; i < 1000; i++) {
????????????????????????????????????????random.nextBytes(buff);
????????????????????????????????????????MappedByteBuffer buffer = outChannel.map(FileChannel.MapMode.READ_WRITE, position, size);
????????????????????????????????????????buffer.put(buff);
????????????????????????????????????????position += size;
????????????????????????????????}
????????????????????????}
????????????????} catch (IOException ex) {
????????????????????????ex.printStackTrace();
????????????????}
????????????????endTime = System.currentTimeMillis(); //获取结束时间
????????????????System.out.println("程序运行时间: " + (endTime - startTime) + "ms");
? ?
以上是关于笔记:I/O流-内存映射文件的主要内容,如果未能解决你的问题,请参考以下文章
NIOMappedByteBuffer-内存映射文件 I/O
JavaNIO的深入研究4内存映射文件I/O,大文件读写操作,Java nio之MappedByteBuffer,高效文件/内存映射