簡體   English   中英

如何在32位系統上讀取4GB文件

[英]How to read 4GB file on 32bit system

在我的情況下,我有不同的文件讓我們假設我有4GB文件的數據。 我想逐行讀取該文件並處理每一行。 我的一個限制是軟件必須在32位MS Windows上運行,或者在64位上運行少量RAM(最小4GB)。 您還可以假設這些行的處理不是瓶頸。

在當前的解決方案中,我通過ifstream讀取該文件並復制到某個字符串。 這是片段的樣子。

std::ifstream file(filename_xml.c_str());
uintmax_t m_numLines = 0;
std::string str;
while (std::getline(file, str))
{
    m_numLines++;
}

好的,這是有效的,但在這里慢慢地是我的3.6 GB數據的時間:

real    1m4.155s
user    0m0.000s
sys     0m0.030s

我正在尋找一種比這更快的方法,例如我發現如何快速解析C ++中空格分隔的浮點數? 我喜歡用boost :: mapped_file提出解決方案,但我遇到了另一個問題,如果我的文件是大的,在我的情況下文件1GB大到足以放棄整個過程。 我必須關心內存中的當前數據,可能使用該工具的人沒有安裝超過4 GB的RAM。

所以我發現了來自boost的mapped_file但是在我的情況下如何使用它? 是否可以部分讀取該文件並接收這些行?

也許你有另一個更好的解決方案。 我必須處理每一行。

謝謝,
巴特

很高興看到你找到我的基准如何快速解析C ++中空格分隔的浮點數?

看來你真的在尋找最快的計算線數(或任何線性單程分析),我已經完成了類似的分析和基准

有趣的是,您會發現性能最高的代碼根本不需要依賴內存映射。

static uintmax_t wc(char const *fname)
{
    static const auto BUFFER_SIZE = 16*1024;
    int fd = open(fname, O_RDONLY);
    if(fd == -1)
        handle_error("open");

    /* Advise the kernel of our access pattern.  */
    posix_fadvise(fd, 0, 0, 1);  // FDADVICE_SEQUENTIAL

    char buf[BUFFER_SIZE + 1];
    uintmax_t lines = 0;

    while(size_t bytes_read = read(fd, buf, BUFFER_SIZE))
    {
        if(bytes_read == (size_t)-1)
            handle_error("read failed");
        if (!bytes_read)
            break;

        for(char *p = buf; (p = (char*) memchr(p, '\n', (buf + bytes_read) - p)); ++p)
            ++lines;
    }

    return lines;
}

具有小內存的64位系統的情況應該可以很好地加載一個大文件 - 這都是關於地址空間 - 雖然它可能比那個情況下的“最快”選項慢,但它實際上取決於其他什么是在內存中以及有多少內存可用於將文件映射到。 在32位系統中,它不起作用,因為進入文件映射的指針最多不會超過大約3.5GB - 通常大約2GB是最大值 - 再次,取決於可用的內存地址將文件映射到的操作系統。

但是,內存映射文件的好處非常小 - 花費的大部分時間來自實際讀取數據。 使用內存映射的節省來自於在將數據加載到RAM后不必復制數據。 (當使用其他文件讀取機制時,讀取功能會將數據復制到提供的緩沖區中,其中內存映射文件將直接將其填充到正確的位置)。

您可能希望增加ifstream的緩沖區 - 默認緩沖區通常相當小,這會導致大量昂貴的讀取。

您應該能夠使用以下內容執行此操作:

std::ifstream file(filename_xml.c_str());
char buffer[1024*1024];
file.rdbuf()->pubsetbuf(buffer, 1024*1024);

uintmax_t m_numLines = 0;
std::string str;
while (std::getline(file, str))
{
    m_numLines++;
}

有關詳細信息,請參閱此問題:

如何讓IOStream表現更好?

由於這是windows,您可以使用帶有“ex”后綴的本機Windows文件函數:

Windows文件管理功能

特別是GetFileSizeEx(),SetFilePointerEx()等函數。 讀寫函數限制為32位字節計數,讀寫“ex”函數用於異步I / O,而不是處理大文件。

暫無
暫無

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

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