【问题标题】:Writing "\r" with std::cout to file saves previously overwritten lines使用 std::cout 将 "\r" 写入文件可保存先前覆盖的行
【发布时间】:2017-09-25 03:11:45
【问题描述】:

我正在使用 C++ 运行模拟,为了跟踪模拟进度,我将输出写为 std::cout << "\rSimulation progress: " << progress;,根据这个答案 https://stackoverflow.com/a/3057994/4237753。所以对于"\r",我以为我覆盖了前一行,但是当我将输出保存到日志文件时,以前覆盖的行也会被保存,在“覆盖”行的每个实例之前都有一个^M。现在我有大约 100MB 的日志文件,而它们只需要几 KB。

文件外观示例:

^MSimulation progress: 66.500^MSimulation progress: 66.600^MSimulation 
progress: 66.700^MSimulation progress: 66.800^MSimulation progress: 
66.900^MSimulation progress: 67.000^MSimulation progress: 67.100^MSimulation 
progress: 67.200^MSimulation progress: 67.300

我想要的只是最后一个实例

Simulation progress: 67.300

有什么好的方法或标准的方法可以真正去除线条吗?

谢谢!

【问题讨论】:

  • \r 写入std::cout 不会神奇地将之前写入的文本删除到文件中。 C++ 不能以这种方式工作。为此,您必须使用seekp() 重置文件中的输出位置,以便后续写入覆盖现有内容。

标签: c++ c++11 terminal cout cat


【解决方案1】:

没有。终端没有以任何方式标准化。就像文件一样,它们采用字节流,但它们对您提供的输入的反应会有所不同。

即有些能够使用转义语法着色。碰巧的是,您正在使用的终端处理 \r 以返回到行首并重新开始编写。对于文件输出,它只是一个字节,没有任何特殊含义。你甚至不能保证\r 会在你运行它的每个终端上重置线路。它取决于系统。

我最好的建议是将您的 UI 和日志分离。这些通常是不同的事情。您不必将相同的信息放入文件和屏幕中。

为了能够使文件流行为与终端一致,需要编写自定义 fstream 缓冲区,该缓冲区将识别 \r 并回溯到最后一个 \n。听起来不太合理。

【讨论】:

    【解决方案2】:

    \r 是一个输出控制符号。当您将\r 写入文件时,它只是其中的一个附加符号。

    您不能用\r 覆盖文件中的行。

    【讨论】:

    • 啊哈,我明白了。既然你这么说,那就有道理了。谢谢!
    猜你喜欢
    • 2016-04-25
    • 2016-04-11
    • 2018-11-21
    • 2011-11-29
    • 1970-01-01
    • 1970-01-01
    • 2018-02-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多