2分鐘理解文件IO -我對文件IO的理解與實驗對比

本文介紹了不一樣的IO方式以及他們之間的效率比較java

1.一次讀取寫入單個字節(讀取400M的文件浪費了好久,等了好久沒讀取完成,證實其效率不好)數組

 

 1 public class CopyFileDemo {
 2     public static void main(String[] args) throws IOException {
 3         FileInputStream fis = new FileInputStream("a.txt");
 4         FileOutputStream fos = new FileOutputStream("b.txt");
 5         
 6         // 方式一:一次讀取寫入單個字節
 7         int i = 0;
 8         while ((i = fis.read()) != -1) {
 9             fos.write(i);
10         }
11         fos.close();
12         fis.close();
13     }
14 }

 

 

 

2.一次讀取寫入多個字節(讀取400M的文件700ms)app

 1 public class CopyFileDemo {
 2 public static void main(String[] args) throws IOException {
 3   FileInputStream fis = new FileInputStream("a.txt");
 4   FileOutputStream fos = new FileOutputStream("b.txt");
 5   // 方式二:一次讀取寫入一個字節數組
 6   byte[] by = new byte[1024];
 7   int len = 0;
 8   while ((len = fis.read(by)) != -1) {
 9     fos.write(by, 0, len);
10   }
11   fos.close();
12   fis.close(); 
13   }
14 }

3.文件流輸入輸出(讀取400M的文件5000ms,爲何更慢呢,猜想是readline這裏,大神能夠指出來)性能

 1 public class CopyFileDemo3 {
 2 public static void main(String[] args) throws IOException {
 3     BufferedReader br=new BufferedReader(new FileReader("a.txt"));
 4     //若是d文件中有數據,true表示繼續往文件中追加數據
 5     BufferedWriter bw=new BufferedWriter(new FileWriter("d.txt",true));
 6 
 7     String line=null;
 8     //高效字符輸入流的特有方法readline(),每次讀取一行數據
 9     while((line=br.readLine())!=null){
10         bw.write(line);
11         //高效字符輸出流的特有方法newline()
12         bw.newLine();
13         //將緩衝區中的數據刷到目的地文件中
14         bw.flush();
15     }
16     //關閉流,其實關閉的就是java調用的系統底層資源。在關閉前,會先刷新該流。
17     bw.close();
18     br.close();
19 }
20 }

BufferedInputStream 會根據狀況自動爲咱們預讀更多的字節數據到它本身維護的一個內部字節數組緩衝區中,這樣咱們即可以減小系統調用次數,從而達到其緩衝區的目的。因此要明確的一點是 BufferedInputStream 的做用不是減小 磁盤IO操做次數(這個OS已經幫咱們作了),而是經過減小系統調用次數來提升性能的。spa

 

 

4.NIO讀取 (400M的視頻文件,讀取要長達700ms)操作系統

 1 public class ReadDemo{
 2 public static void main(String[] args) throws IOException {
 3      File file = new File("sdtgj.mp4");  
 4      FileInputStream in = new FileInputStream(file);  
 5      FileChannel channel = in.getChannel();  
 6      ByteBuffer buff = ByteBuffer.allocate(1024);   
 7        
 8      long begin = System.currentTimeMillis();  
 9      while (channel.read(buff) != -1) {  
10          buff.flip();  
11          buff.clear();  
12      }  
13      long end = System.currentTimeMillis();  
14      System.out.println("time is:" + (end - begin)+"毫秒   "+"讀取 "+file.getName());  
15 }
16 }

 

5.內存映射讀取 (400M的視頻文件,讀取只要100ms)code

 

 1 public class ReadDemo{
 2  
 3      static final int BUFFER_SIZE = 1024;  
 4       
 5         public static void main(String[] args) throws Exception {  
 6       
 7             File file = new File("sdtgj.mp4");  
 8             FileInputStream in = new FileInputStream(file);  
 9             FileChannel channel = in.getChannel();  
10             MappedByteBuffer buff = channel.map(FileChannel.MapMode.READ_ONLY, 0,  
11                     channel.size());  
12       
13             byte[] b = new byte[1024];  
14             int len = (int) file.length();  
15       
16             long begin = System.currentTimeMillis();  
17       
18             for (int offset = 0; offset < len; offset += 1024) {  
19       
20                 if (len - offset > BUFFER_SIZE) {  
21                     buff.get(b);  
22                 } else {  
23                     buff.get(new byte[len - offset]);  
24                 }  
25             }  
26       
27             long end = System.currentTimeMillis();  
28             System.out.println("time is:" + (end - begin)+"毫秒   "+"讀取 "+file.getName()); 
29       
30         }  
31 }

 

MappedByteBuffer 不受JVM堆大小控制,速度最快。
MappedByteBuffer 的要點:
  1. java經過java.nio包來支持內存映射IO。
  2. 內存映射文件主要用於性能敏感的應用,例如高頻電子交易平臺。
  3. 經過使用內存映射IO,你能夠將大文件加載到內存
  4. 內存映射文件可能致使頁面請求錯誤,若是請求頁面不在內存中的話。
  5. 映射文件區域的能力取決於於內存尋址的大小。在32位機器中,你不能訪問超過4GB或2 ^ 32(以上的文件)。
  6. 內存映射IO比起Java中的IO流要快的多。
  7. 加載文件所使用的內存是Java堆區以外,並駐留共享內存,容許兩個不一樣進程共享文件。
  8. 內存映射文件讀寫由操做系統完成,因此即便在將內容寫入內存後java程序崩潰了,它將仍然會將它寫入文件直到操做系統恢復。
  9. 出於性能考慮,推薦使用直接字節緩衝而不是非直接緩衝。
  10. 不要頻繁調用MappedByteBuffer.force()方法,這個方法意味着強制操做系統將內存中的內容寫入磁盤,因此若是你每次寫入內存映射文件都調用force()方法,你將不會體會到使用映射字節緩衝的好處,相反,它(的性能)將相似於磁盤IO的性能。
  11. 萬一發生了電源故障或主機故障,將會有很小的機率發生內存映射文件沒有寫入到磁盤,這意味着你可能會丟失關鍵數據。
相關文章
相關標籤/搜索