C++ 以缓冲速率从 STDIN 读取输入

Posted

技术标签:

【中文标题】C++ 以缓冲速率从 STDIN 读取输入【英文标题】:C++ Read input from STDIN at a buffered rate 【发布时间】:2015-04-10 21:32:46 【问题描述】:

我正在获取一个 txt 文件的内容并将其传送到我的应用程序中,如下所示。

猫文件.txt | ./app [参数]

我的问题是,我当前处理应用程序的方式本质上是获取“file.txt”的全部内容并将其存储在 STDIN 中。

这适用于相对较小的文件,但如果 TXT 文件太大会导致应用程序崩溃/溢出。

我正在寻找一种解决方案,它允许我以“缓冲速率”从文件中读取数据,这样在程序开始时不会存储文件的全部内容。

她是我目前如何接受输入的一个 sn-p。

  std::vector<string> lines = LinesInFile(std::cin);  // Storing lines

它利用了以下函数。

std::vector<std::string> LinesInFile(std::istream& input_file) 
  std::string text_from_input;
  std::vector<std::string> lines_from_file;

    while (std::getline(input_file, text_from_input)) 
      lines_from_file.push_back(text_from_input);
    
return lines_from_file;

这目前有效,并将采用正确的输入。但显然这不是生产性代码,并且可能会出现一些更大的问题。

我只想“处理”来自 TXT 文件的数据,而不是将文件的全部内容存储在内存中。

我目前正在使用 C++,所以我不想使用旧的标准 C 函数。老实说,我更喜欢 C++11 及更高版本。

提前感谢您的帮助。

编辑:

我想澄清一下,我首先将每个单独的行存储在向量中以单独处理每一行。我知道我可以处理每一行,但这仍然会带来一个潜在的问题,如果文件不包含换行符,那么我仍然会有溢出和潜在问题的风险。

编辑:

我知道这在大多数情况下是极不可能的。但是,这不是我对这篇文章的关注。

【问题讨论】:

那么为什么不处理 while 内的行而不是将它们推入数组? 嗯,最初我所做的是获取每一行并将其数据推回向量中。完成分离和存储每一行​​后,我将返回该向量并稍后在不同进程中使用该向量。 基本上我正在处理每一行。在这一点上,我认为我可以在处理文件时内联处理数据并搜索“\n”或 EOF。而不是像我现在一样拆分每一行。我需要改进我的方法的部分帮助,我会让 ATM 有点乱。 如果我只逐行处理,另一个潜在问题是,如果文件永远没有返回字符。那么它将基本上是一条巨大的线,我将再次遇到我可能的溢出问题。 stdin 默认缓冲。但是您编写了代码来一次提取所有内容并将其保存在内存中?好吧,那就不要那样做。一次处理每一行。这太奇怪了,我不确定我是否完全理解这个问题。如果一行不包含换行符,则没有溢出问题,唯一的问题是 bad_alloc。正确的做法是打印错误并退出。实际上很简单。 【参考方案1】:

这适用于相对较小但会导致 如果 TXT 文件太大,应用程序会崩溃/溢出。

我怀疑你的担心为时过早。

无论有多少字符串或多少字节,我系统上的向量在堆栈中的大小约为 12 个字节。虽然我还没有确认,但我认为这意味着你的向量的内容驻留在你的堆中。

我的机器有 4 GB 的内存,在交换中也是如此(尽管交换会非常慢)。填充这么多内存需要一个非常大的文件。

我定期使用 std::stringstream 将整个文件传输到 ram,如下所示:

  m_ss << sIn.rdbuf();
  if(sIn.bad())
     throw "DTB::Filter::load()  'm_ss << sIn bad after rdbuff()'";

然后要么从字符串流中正常逐行处理它,或者,有时我采用捷径并将整个文件作为使用 stringstream.str() 复制的单个字符串处理

检查你的计划——你的文本文件会比你的内存大吗?


接下来考虑按照您现在的计划构建它。

改成逐行处理有多难?

像我一样使用 stringstream,重构非常简单。 RAM 也比(大多数)我的驱动器快得多。

虽然我还没有发现需要,但可以统计文件并让您的代码在运行时确定其大小足以跳过字符串流或向量临时存储。

1)“从内存中加载容器 + 逐行处理”是否比 2)“逐行处理文件”花费更多时间?

我不知道。我不使用千兆字节的文本文件,但我想我可以创建一个并测量它......也许稍后当我遇到真正的需要时。

【讨论】:

您认为这几乎不会发生是正确的。我只是关心以更好/正确的方式执行此操作以获得最佳实践。我最近开始真正理解其中一些“可能永远不会发生但可以”的解决方案,以获取更多知识。 基本上,如果它确实发生了。我会倒霉的。或者,如果这是一个不同的场景。我想考虑这一点的更好方法是缓冲管道输入,而不是直接存储整个内容。如果在这种情况下我什至不使用 txt 文件。

以上是关于C++ 以缓冲速率从 STDIN 读取输入的主要内容,如果未能解决你的问题,请参考以下文章

在 C 中使用 fread 从标准输入缓冲读取

scanf()函数分析

如何在 Perl 中读取和写入大缓冲区到进程 stdin/stdout/stderr?

解决linux下fflush(stdin)无效

解决linux下fflush(stdin)无效

C++非阻塞键盘缓冲区输入检测或读取函数是啥?