RandomAcessFile、MappedByteBuffer和缓冲读/写文件

时间:2021-03-19 19:41:25

http://blog.csdn.net/kissqw/article/details/6555911

项目需要进行大文件的读写,调查测试的结果使我决定使用MappedByteBuffer及相关类进行文件的操作,效果不是一般的高。

网上参考资源很多,如下两篇非常不错:

1、花1K内存实现高效I/O的RandomAccessFile类
2、Java中Stream和Memory-mapped File的I/O性能对比
小结:
1、RandomAccessFile本身不带缓冲读写,和FileInputStream、FileOutputStream等一样,直接按字节读写时,性能不可接受;
2、使用MappedByteBuffer读写,固然性能会得到极大提升;其实只要自己处理缓冲,性能都会有非常大的提升,比如以下两种方式(见下记代码)中第一种使用了MappedByteBuffer,第二种自己进行缓冲,对于12M的文件,后者的效率甚至高于前者。
3、BufferedXXXX之类的缓冲流,如果仅使用默认的buffer size,性能不一定最优,要权衡不同情况各种因素设置大小。
[java] view plaincopy
  
  
  1. /* 
  2.  * 测试结果与Buffer size有关 
  3.  */  
  4. // 1、使用MappedByteBuffer: 0.7s  
  5. String srcFile = "D://Noname1.txt";  
  6. String destFile = "D://copy.txt";  
  7. RandomAccessFile rafi = new RandomAccessFile(srcFile, "r");  
  8. RandomAccessFile rafo = new RandomAccessFile(destFile, "rw");  
  9. FileChannel fci = rafi.getChannel();  
  10. FileChannel fco = rafo.getChannel();  
  11. long size = fci.size();  
  12. MappedByteBuffer mbbi = fci.map(FileChannel.MapMode.READ_ONLY, 0, size);  
  13. MappedByteBuffer mbbo = fco.map(FileChannel.MapMode.READ_WRITE, 0, size);  
  14. long start = System.currentTimeMillis();  
  15. for (int i = 0; i < size; i++) {  
  16.     byte b = mbbi.get(i);  
  17.     mbbo.put(i, b);  
  18. }  
  19. fci.close();  
  20. fco.close();  
  21. rafi.close();  
  22. rafo.close();  
  23. System.out.println("Spend: " + (double) (System.currentTimeMillis() - start) / 1000 + "s");  
  24.   
  25.   
  26. // 2、自己处理Buffer(RandomAccessFile): 0.13s      
  27. String srcFile = "D://Noname1.txt";  
  28. String destFile = "D://copy.txt";  
  29. RandomAccessFile rafi = new RandomAccessFile(srcFile, "r");  
  30. RandomAccessFile rafo = new RandomAccessFile(destFile, "rw");  
  31.   
  32. byte[] buf = new byte[1024 * 8];  
  33.   
  34. long start = System.currentTimeMillis();  
  35.   
  36. int c = rafi.read(buf);  
  37.   
  38. while (c > 0) {  
  39.     if (c == buf.length) {  
  40.         rafo.write(buf);  
  41.     } else {  
  42.         rafo.write(buf, 0, c);  
  43.     }  
  44.   
  45.     c = rafi.read(buf);  
  46. }  
  47. rafi.close();  
  48. rafo.close();  
  49. System.out.println("Spend: " + (double) (System.currentTimeMillis() - start) / 1000 + "s");  
  50.   
  51.   
  52. // 3、BufferedInputStream&BufferedOutputStream: 3.02s  
  53. String srcFile = "D://Noname1.txt";  
  54. String destFile = "D://copy.txt";  
  55. FileInputStream rafi = new FileInputStream(srcFile);  
  56. FileOutputStream rafo = new FileOutputStream(destFile);  
  57.   
  58. BufferedInputStream bis = new BufferedInputStream(rafi, 8192);  
  59. BufferedOutputStream bos = new BufferedOutputStream(rafo, 8192);  
  60. long size = rafi.available();  
  61.   
  62. long start = System.currentTimeMillis();  
  63.   
  64. for (int i = 0; i < size; i++) {  
  65.     byte b = (byte) bis.read();  
  66.     bos.write(b);  
  67. }  
  68. rafi.close();  
  69. rafo.close();  
  70. System.out.println("Spend: " + (double) (System.currentTimeMillis() - start) / 1000 + "s");