内存映射文件 I/O 是一种读和写文件数据的方法,它可以比常规的基于流或者基于通道的 I/O 快得多。
内存映射文件 I/O 是通过使文件中的数据神奇般地出现为内存数组的内容来完成的。这其初听起来似乎不过就是将整个文件读到内存中,但是事实上并不是这样。一般来说,只有文件中实际读取或者写入的部分才会送入(或者 映射 )到内存中。
内存映射并不真的神奇或者多么不寻常。现代操作系统一般根据需要将文件的部分映射为内存的部分,从而实现文件系统。Java 内存映射机制不过是在底层操作系统中可以采用这种机制时,提供了对该机制的访问。
尽管创建内存映射文件相当简单,但是向它写入可能是危险的。仅只是改变数组的单个元素这样的简单操作,就可能会直接修改磁盘上的文件。修改数据与将数据保存到磁盘是没有分开的。
以下是将一个118M的文件进行拷贝
public class MapMemeryBuffer {
private static String fileName = "file/test.txt";
private static String fileName1 = "file/test2.txt";
public static void main(String[] args) throws Exception {
mapBufferWriteFile();
}
public static long length;
public static ByteBuffer mapBufferReadFile() {
try {
RandomAccessFile fis = new RandomAccessFile(fileName, "r");
FileChannel fc = fis.getChannel();
length = fc.size();
MappedByteBuffer mbb = fc.map(FileChannel.MapMode.READ_ONLY, 0,
length);
return mbb.get(new byte[(int) fc.size()]);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
public static void mapBufferWriteFile() {
try {
long start = System.currentTimeMillis();
// FileOutputStream fos = new FileOutputStream(fileName1);
RandomAccessFile fos = new RandomAccessFile(fileName1, "rw");
FileChannel fc = fos.getChannel();
ByteBuffer bb = mapBufferReadFile();
MappedByteBuffer mbb = fc.map(FileChannel.MapMode.READ_WRITE, 0,
length);
for (int i = 0; i < length; i++) {
mbb.put(i, bb.get(i));
}
mbb.flip();
System.out.println(System.currentTimeMillis() - start);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
测试时间在在2.2s左右,文件处理非常快。
在写测试用例的时候文件读取的时候使用FileInputStream没有什么问题,可是在文件写的时候使用FileOutputStream则报错所以改成了RandomAccessFile