【发布时间】:2015-10-17 18:42:33
【问题描述】:
我有一个格式如下的文件:
1: some_basic_info_in_this_line
2: LOTS_OF_INFO_IN_THIS_LINE_HUNDREDS_OF_CHARS
3: some_basic_info_in_this_line
4: LOTS_OF_INFO_IN_THIS_LINE_HUNDREDS_OF_CHARS
...
这种格式会重复数万次,使文件达到 50 GiB+。我需要一种有效的方法来处理这种格式的唯一第 2 行。我愿意使用 C、C++11 STL 或 boost。我已经查看了有关 SO 上文件流式传输的各种其他问题,但我觉得我的情况很独特,因为文件很大,而且每四行只需要一行。
内存映射文件似乎是我读过的最有效的文件,但映射 50+ GB 的文件会占用大多数计算机的 RAM(您可以假设此应用程序将由“普通”用户使用 - 比如说4-8 GiB RAM)。此外,我一次只需要处理其中一条线。以下是我目前的做法(是的,我知道这效率不高,这就是我重新设计它的原因):
std::string GL::getRead(ifstream& input)
{
std::string str;
std::string toss;
if (input.good())
{
getline(input, toss);
getline(input, str);
getline(input, toss);
getline(input, toss);
}
return str;
}
将 mmap 分解成块是否适合我的情况?无论如何,我可以利用 4 行中的 1 行吗?感谢您的帮助。
【问题讨论】:
-
再一次,我想知道谁对此投了反对票。这是一个足够有趣的问题,而且提出得很好。 +1
-
如果您的格式严格定义为行大小,您可以使用 input.seekg 跳过不需要的行
-
主要瓶颈将在输入操作本身。我建议您尝试各种方法在典型用户的计算机上逐块加载数据。不知道如何最好地处理跨越两个街区的线(大多数街区都会有这样的线)。
-
在返回
str之前检查输入操作是否成功通常是个好主意——调用者应该检查输入中是否设置了任何标志,它只是eof而不是bad或fail,但还要在某个阶段检查eof- 仅在输入之前让getRead()检查input.good()- 如果其余部分正确完成,则该检查应该是多余的。 -
就像 Nir 说的,你必须检查每个字符是否是换行符,除非你可以根据文件格式的规则跳过一些。
strchr或任何用于内部寻找换行符的东西都应该能够轻松跟上磁盘读取带宽,即使是从体面的 SSD。
标签: c++ performance c++11 boost