簡體   English   中英

如何在 Java 中讀取大文件(單個連續字符串)?

[英]How to read large files (a single continuous string) in Java?

我正在嘗試讀取一個非常大的文件(~2GB)。 內容是一個帶有句子的連續字符串(我想根據'.'將它們分開)。 無論我如何嘗試,最終都會出現 Outofmemory 錯誤。

    BufferedReader in = new BufferedReader(new FileReader("a.txt"));
    String read = null;
    int i = 0;
    while((read = in.readLine())!=null) {
        String[] splitted = read.split("\\.");
        for (String part: splitted) {
            i+=1;
            users.add(new User(i,part));
            repository.saveAll(users);
        }
    }

還,

inputStream = new FileInputStream(path);
    sc = new Scanner(inputStream, "UTF-8");
    while (sc.hasNextLine()) {
        String line = sc.nextLine();
        // System.out.println(line);
    }
    // note that Scanner suppresses exceptions
    if (sc.ioException() != null) {
        throw sc.ioException();
    }

文件內容(由 10 個詞后有句號的隨機詞組成):

fmfbqi .xcdqnjqln kvjhw pexrbunnr cgvrqlr fpaczdegnb puqzjdbp gcfxne jawml aaiwwmo ugzoxn .opjc fmfbqi .xcdqnjqln kvjhw pexrbunnr cgvrqlr fpaczdegnb puqzjdbp gcfxne jawml aaiwwmo ugzoxn .opjc  (so on)

請幫忙!

首先,根據對您的問題的評論,正如 Joachim Sauer 所說:

如果沒有換行符,則只有一行,因此只有一個行號。

所以你的用例充其量是有問題的。

讓我們超越它,假設可能有換行符 - 或者更好的是,假設. 您要拆分的字符旨在成為換行符偽替換。

Scanner在這里並不是一個糟糕的方法,盡管還有其他方法。 由於您提供了Scanner ,讓我們繼續,但您要確保將它包裝在BufferedReader周圍。 您顯然沒有很多內存,並且BufferedReader允許您讀取由BufferedReader緩沖的文件的“塊”,同時利用Scanner的功能對您來說完全模糊,因為您作為正在發生緩沖的調用者:

Scanner sc = new Scanner(new BufferedReader(new FileReader(new File("a.txt")), 10*1024));

這基本上做的是讓Scanner按您的預期運行,但允許您一次緩沖 10MB,從而最大限度地減少內存占用。 現在,你只要繼續打電話

sc.useDelimiter("\\.");
for(int i = 0; sc.hasNext(); i++) {
    String psudeoLine = sc.next();
    //store line 'i' in your database for this psudeo-line
    //DO NOT store psudeoLine anywhere else - you don't have memory for it
}

由於您沒有足夠的內存,因此迭代(和重新迭代)的明確事項是在讀取文件后不要將文件的任何部分存儲在 JVM 的堆空間中。 閱讀它,根據需要使用它,並允許將其標記為 JVM 垃圾收集。 在您的情況下,您提到要將偽行存儲在數據庫中,因此您想讀取偽行,將其存儲在數據庫中,然后將其丟棄。

這里還有其他事情要指出,例如配置您的 JVM 參數,但我什至不願提及它,因為僅將 JVM 內存設置為高也是一個壞主意 - 另一種蠻力方法。 將 JVM 內存最大堆大小設置得更高並沒有錯,但是如果您仍在學習如何編寫軟件,那么學習內存管理會更好。 當你進入職業發展階段時,你會遇到更少的麻煩。

另外,我提到了ScannerBufferedReader是因為您在問題中提到了這一點,但我認為查看 deHaar 指出的java.nio.file.Path.lines()也是一個好主意。 這基本上與我明確列出的代碼做同樣的事情,但需要注意的是,它仍然一次只執行 1 行,而無法更改您正在“拆分”的內容。 所以如果你的文本文件只有 1 行,這仍然會給你帶來問題,你仍然需要像掃描儀這樣的東西來分割行。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM