繁体   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