2017-05-04 72 views
-6

這個問題很短。 我有一個文件閱讀3GB文件無例外

Datei.trec-3,99 GB,我使用此代碼閱讀:

public class Main { 
    public static void main(String[] args) { 
     byte[] content = null; 
     try { 
      content = Files.readAllBytes(Paths.get("D:", "Videos","Captures","Datei.trec")); 
     } catch (IOException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 
     System.out.println(content); 
    } 
} 

,這是輸出:

Exception in thread "main" java.lang.OutOfMemoryError: Required array size too large 
    at java.nio.file.Files.readAllBytes(Unknown Source) 
    at Main.main(Main.java:13) 

所以是有一個沒有異常寫入數組的選項(FileInputStream等)?

+0

內容是一個有限的大小的數組,你是溢出.... –

+0

我知道,但我應該如何閱讀內容呢? – Niton

+3

你會流它。讀取一些數據,做你需要的東西,讀下一個位等 – pandaadb

回答

3

的問題是,以容納所有這些數據所需要的陣列比MAX_BUFFER_SIZE更大,這是在定義java.nio.FilesInteger.MAX_VALUE - 8

public static byte[] readAllBytes(Path path) throws IOException { 
     try (SeekableByteChannel sbc = Files.newByteChannel(path); 
      InputStream in = Channels.newInputStream(sbc)) { 
      long size = sbc.size(); 
      if (size > (long)MAX_BUFFER_SIZE) 
       throw new OutOfMemoryError("Required array size too large"); 

      return read(in, (int)size); 
     } 
    } 

這是必要的,因爲數組通過整數進行索引 - 這是您可以獲得的最大數組。

你有三個選擇:

流通過文件

也就是說,打開文件,讀取塊,處理它,閱讀另一塊,對它進行處理,一次又一次,直到你」已經經歷了整個事情。

Java提供了很多類來執行此操作:InputStream,Reader,Scanner等 - 它們在大多數Java入門課程和書籍中都有討論。研究其中之一。

https://stackoverflow.com/a/21706141/7512

這樣做的有效性取決於你能夠做一些有意義的事情與文件的早期部分,不知道將會發生什麼。很多時候都是這樣。其他時候,您必須在文件中進行多次傳遞。

文件格式通常被設計爲可以一次完成處理 - 根據這個設計自己的文件格式是一個不錯的主意。

我注意到你的文件是一個.trec文件,它是一個屏幕捕獲的視頻。視頻和音頻格式很可能是爲流媒體而設計的 - 這是您可以在下載結束之前觀看YouTube視頻的開始的原因。

內存映射

如果你真的需要跳來跳去的文件來處理它的內容,你可以作爲一個內存映射文件打開它。

查看RandomAccessFile的文檔 - 這爲您提供了一個seek()方法的對象,因此您可以讀取文件數據中的任意點。

閱讀到多個陣列

我包括這僅出於完整性;將整個文件整理成堆內存很難。但如果你真的想,你可以將這些字節存儲在一些數組中 - 也許是List<byte[]>。 Java-ish僞代碼:

List<byte[]> filecontents = new ArrayList<byte[]>(); 
    InputStream is = new FileInputStream(...); 
    byte[] buffer = new byte[MAX_BUFFER_SIZE]; 
    int bytesGot = readUpToMaxBufferSizeFrom(file); 
    while(bytesGot != -1) { 
     byte[] chunk = new byte[bytesGot]; 
     System.arrayCopy(buffer, 0, chunk, 0, bytesGot); 
     filecontents.add(chunk); 
    } 

這允許你達到MAX_BUFFER_SIZE * Integer.MAX_INTEGER字節。訪問內容比使用簡單的數組稍微複雜一點 - 但是實現細節可以隱藏在類中。

你會的,當然,需要配置的Java有一個巨大的堆大小 - 見How to set the maximum memory usage for JVM?

不要這樣做。

+1

道歉,增加堆大小無助於 - 刪除該部分,並解釋了關於'MAX_BUFFER_SIZE' – slim

+0

感謝您的答覆 – Niton

0

我建議你通過文件流;可以使用例如LineIterator,從Apache的百科全書:

LineIterator it = FileUtils.lineIterator(theFile, "UTF-8"); 
try { 
    while (it.hasNext()) { 
     String line = it.next(); 
    } 
} finally { 
    LineIterator.closeQuietly(it); 
} 
+0

我需要收集一個變量中的全部內容(數組或數據類型) – Niton