day2:将原来普通读取文件的方式改为内存映射文件的方式。
mmap 是一种内存映射文件的方法,即将一个文件映射到进程的地址空间,实现文件磁盘地址和一段进程虚拟地址的映射
Java 中的 mmap
Java 中原生读写方式大概可以被分为三种:普通 IO,FileChannel(文件通道),mmap(内存映射)。区分他们也很简单,例如 FileWriter,FileReader 存在于 java.io 中,他们属于普通 IO;FileChannel 存在于 java.nio 中,也是 Java 最常用的文件操作类;而今天的主角 mmap,则是由 FileChannel 调用 map 方法衍生出来的一种特殊读写文件的方式,被称之为内存映射。
mmap 的使用方式:
FileChannel fileChannel = new RandomAccessFile(new File("db.data"), "rw").getChannel();
MappedByteBuffer mappedByteBuffer = fileChannel.map(FileChannel.MapMode.READ_WRITE, 0, filechannel.size();
MappedByteBuffer 便是 Java 中的 mmap 操作类。
// 写
byte[] data = new byte[4];
int position = 8;
// 从当前 mmap 指针的位置写入 4b 的数据
mappedByteBuffer.put(data);
// 指定 position 写入 4b 的数据
MappedByteBuffer subBuffer = mappedByteBuffer.slice();
subBuffer.position(position);
subBuffer.put(data);
// 读
byte[] data = new byte[4];
int position = 8;
// 从当前 mmap 指针的位置读取 4b 的数据
mappedByteBuffer.get(data);
// 指定 position 读取 4b 的数据
MappedByteBuffer subBuffer = mappedByteBuffer.slice();
subBuffer.position(position);
subBuffer.get(data);
回收 mmap 内存
更正之前博文关于 mmap 内存回收的一个错误说法,回收 mmap 很简单。
((DirectBuffer) mmap).cleaner().clean();
作业代码:
import java.io.*;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
public class day2 {
public static void main(String[] args) throws IOException{
String filePath = "src/picture/day1.png";
FileChannel fileChannel = null;
try {
fileChannel = new RandomAccessFile(new File(filePath), "rw").getChannel();
MappedByteBuffer mappedByteBuffer = fileChannel.map(FileChannel.MapMode.READ_WRITE, 0, fileChannel.size());
byte[] bytes = new byte[64];
mappedByteBuffer.get(bytes);
print(bytes);
mappedByteBuffer.position((int)fileChannel.size()-64);
mappedByteBuffer.get(bytes);
print(bytes);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
if(fileChannel !=null){
try {
fileChannel.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public static void print(byte[] bytes)
{
for (int i = 0; i < bytes.length; i++) {
System.out.printf("%02X ",bytes[i]);
if((i+1)%8==0) System.out.print("\n");
}
System.out.println("-----------------");
}
}