内存映射文件是java NIO模块里非常有用的一个功能,它通过FileChannel中的map方法将文件片段映射到内存中,并且可以直接将对内存的操作反应到文件中,非常适合对大文件的操作,并且效率相比传统的字节IO流效率高出不少。
以下是我实现的一个简单的文件编辑器。
1 /** 2 * 文件编辑器 3 * @author rui.chen 4 * 5 */ 6 public class MyFileEditor { 7 private FileChannel channel; 8 private RandomAccessFile file; 9 10 public MyFileEditor(String path){ 11 try { 12 File f = new File(path); 13 if(!f.exists() || !f.isFile()){ 14 f.createNewFile(); 15 } 16 file = new RandomAccessFile(f, "rw"); 17 } catch (Exception e) { 18 e.printStackTrace(); 19 } 20 } 21 22 public void open(){ 23 channel = file.getChannel(); 24 } 25 26 /** 27 * 在文件末尾添加内容 28 */ 29 public void append(String content){ 30 try { 31 override(content, (int) file.length()); 32 } catch (IOException e) { 33 e.printStackTrace(); 34 } 35 } 36 37 /** 38 * 在position位置写入content,并覆盖原有内容 39 */ 40 public void override(String content, int position){ 41 try { 42 MappedByteBuffer buffer = channel.map(MapMode.READ_WRITE, position, content.length()); 43 buffer.position(0); 44 buffer.put(content.getBytes()); 45 buffer.flip(); 46 } catch (IOException e) { 47 e.printStackTrace(); 48 } 49 } 50 51 /** 52 * 在position位置插入内容,不覆盖原有内容 53 */ 54 public void insert(String content, int position){ 55 try { 56 int length = (int) (file.length()-position+content.length()); 57 int fileLen = (int) file.length(); 58 MappedByteBuffer buffer = channel.map(MapMode.READ_WRITE, 59 position, length); 60 buffer.position(0); 61 byte[] dst = new byte[length]; 62 byte[] contentBytes = content.getBytes(); 63 for(int i=0; i<contentBytes.length; i++){ 64 dst[i] = contentBytes[i]; 65 } 66 byte[] old = new byte[fileLen-position]; 67 buffer.get(old, 0, fileLen-position); 68 buffer.position(0); 69 for(int i=0; i<old.length; i++){ 70 dst[i+contentBytes.length] = old[i]; 71 } 72 buffer.put(dst); 73 buffer.flip(); 74 } catch (IOException e) { 75 e.printStackTrace(); 76 } 77 } 78 79 public void close(){ 80 if(channel.isOpen()){ 81 try { 82 channel.close(); 83 } catch (IOException e) { 84 e.printStackTrace(); 85 } 86 } 87 } 88 }
通过下面的测试程序进行测试,文件大小为516MB,运行时间为44毫秒。
1 public class NIOTest { 2 public static void main(String[] args){ 3 MyFileEditor editor = new MyFileEditor("D:\\server.log.2013-05-02"); 4 editor.open(); 5 long start = System.currentTimeMillis(); 6 editor.append("content be appended"); 7 System.out.println("time cost: "+(System.currentTimeMillis()-start)+" milliseconds"); 8 editor.close(); 9 } 10 }