2012-02-01 84 views
10

用Java的I/O方法讀取相對較大的文件可能是最快的方法是什麼?我當前的解決方案使用BufferedInputStream保存到分配有1024字節的字節數組中。每個緩衝區都保存在ArrayList以備後用。整個過程通過一個單獨的線程(可調用接口)調用。在Java中讀取相對較大的字節文件的最快方法

雖然不是很快。

ArrayList<byte[]> outputArr = new ArrayList<byte[]>();  
    try { 
     BufferedInputStream reader = new BufferedInputStream(new FileInputStream (dir+filename)); 

     byte[] buffer = new byte[LIMIT]; // == 1024 
      int i = 0; 
      while (reader.available() != 0) { 
       reader.read(buffer); 
       i++; 
       if (i <= LIMIT){ 
        outputArr.add(buffer); 
        i = 0; 
        buffer = null; 
        buffer = new byte[LIMIT]; 
       } 
       else continue;    
      } 

     System.out.println("FileReader-Elements: "+outputArr.size()+" w. "+buffer.length+" byte each."); 
+0

查看Apache Commons庫以獲取更多選項。爲了確定速度,請看O'Reilly的Java Performance Tuning一書。 – therobyouknow 2012-02-01 10:03:07

+5

目前,您正在忽略read()調用返回的值。 *不要那樣做。* – 2012-02-01 10:06:34

回答

25

我會使用一個內存映射文件,它足夠快,可以在同一個線程中執行。

final FileChannel channel = new FileInputStream(fileName).getChannel(); 
MappedByteBuffer buffer = channel.map(FileChannel.MapMode.READ_ONLY, 0, channel.size()); 

// when finished 
channel.close(); 

這假設文件小於2 GB,並且需要10毫秒或更少。

+1

血腥地獄!爲什麼這件事太快了?無論如何,完美的作品。 (編輯:它從內存中獲取文件,java文檔只是告訴我。聰明) – 2012-02-01 15:42:39

+1

如果你需要訪問超過2 GB的數據,你需要使用多個映射。 – 2012-02-01 21:42:11

3

請勿使用available():這不可靠。並且不要忽略read()方法的結果:它會告訴您實際讀取的字節數。如果你想讀內存中的所有,使用一個ByteArrayOutputStream,而不是使用List<byte[]>

ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
int read; 
while ((read = reader.read(buffer)) >= 0) { 
    baos.write(buffer, 0, read); 
} 
byte[] everything = baos.toByteArray(); 

我覺得1024有點小爲緩衝大小。我會使用更大的緩衝區(類似於16 KB或32 KB)

請注意,Apache commons IO和Guava具有爲您實現此目的的實用方法,並且已經進行了優化。

1

查看Java NIO(非阻塞輸入/輸出)API。此外,this question可能被證明是有用的。

我沒有太多的IO經驗,但我聽說NIO是更有效的方式處理大型數據集。

相關問題