操作系统会在负责执行映射,用于操作大文件
java io操作中通常采用BufferedReader,BufferedInputStream等带缓冲的IO类处理大文件;java nio中引入了一种基于MappedByteBuffer操作大文件的方式,其读写性能极高
FileChannel提供了map方法把文件映射到虚拟内存,通常情况可以映射整个文件,如果文件比较大,可以进行分段映射
MappedByteBuffer mbb = fc.map(FileChannel.MapMode.READ_WRITE, 0, 1024); //fc-->FileChannel
//map通过native函数map0完成文件的映射工作,返回DirectByteBuffer
MappedByteBuffer的get方法最终通过DirectByteBuffer.get方法实现的
public byte get() { return ((unsafe.getByte(ix(nextGetIndex()))));}public byte get(int i) { return ((unsafe.getByte(ix(checkIndex(i)))));}private long ix(int i) { return address + (i << 0);}
map0()函数返回一个地址address,这样就无需调用read或write方法对文件进行读写,通过address就能够操作文件。底层采用unsafe.getByte方法,通过(address + 偏移量)获取指定内存的数据。
从代码层面上看,从硬盘上将文件读入内存,都要经过文件系统进行数据拷贝,并且数据拷贝操作是由文件系统和硬件驱动实现的,理论上来说,拷贝数据的效率是一样的。
但是通过内存映射的方法访问硬盘上的文件,效率要比read和write系统调用高,这是为什么?
所以,采用内存映射的读写效率要比传统的read/write性能高