簡體   English   中英

從Java中的大文件讀取特定行

[英]Reading specific lines from a large file in Java

我目前正在文件處理方面進行練習,需要在給定行號的情況下讀取巨大文本文件中的特定行(僅包含ASCII字符的千兆字節文件)。

到目前為止,我所做的是:

由於該文件沒有大小相等的行,因此我對該文件進行了處理,以創建一個與行號相對應的每行偏移量的哈希表(冷啟動)。 隨后,使用偏移量查找隨機訪問文件(給定的文本文件)。 這種方法的問題是,對於非常大的文件大小,內存不足以容納Hashmap,而且I / O成為瓶頸。 我的系統規格是:8GB DDR2、1TB(SATA2)7200RPM,4-64位內核。 讓我們假設整個硬件都可以使用。

我打算做什么

為了最大程度地減少延遲,我打算將文本文件中的所有行都索引到頁面中,並根據是否存在包含請求的行號的頁面,使用“最近最少使用的頁面替換”策略將必要的頁面分頁到內存中。是否在內存中。 (就像緩存一樣),我知道這很大程度上取決於頁面大小和內存中的常駐頁面數,但我確實需要知道我是朝着更有意義的方向前進,還是只是成為一個有意義的方向。過度殺傷力?

感謝您的所有幫助和建議。

每行偏移量的哈希圖

這就是問題所在。 映射可能比文件本身更容易消耗更多的內存。

存儲每第1024行的偏移量將需要少1024倍的內存。 由於以下原因,從磁盤讀取一行或一千行大約需要相同的時間:

  • 最小的可訪問單元是一個塊(以前是512 B,現在是4KiB)
  • 與尋道時間相比,塊的傳輸時間可以忽略不計

因此,四舍五入到1024的倍數,找到該行並按順序處理到您真正想要的行。


您正在使用HashMap<Integer, Integer> ,它為裝箱的int占用大量內存。 但是您的鍵會建立一個序列,那么為什么不使用List<Integer>甚至int[]呢? 您可以將內存消耗減少大約4倍。

我想通過以下方式訪問List<int[]> offsets

int getOffset(int line) {
    int listIndex = line >> 20; // one list entry per 1M lines
    int arrayIndex = (line >> 10) & 1023; one array entry per 1k lines
    int remaining = line & 1023; // lines to skip

    // TODO: handling of index bounds
    int offset = offsets.get(listIndex)[arrayIndex];
    **seek to offset
    **skip remaining lines
}

每1024行需要4個字節(一個int ),每1MiB需要更多的內存。 除非文本文件為多terrabyte,否則不需要LRU,因為一切都非常合適。

對於大文件,請在上述文本中long替換int

暫無
暫無

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

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