我正在为 Mac OS X 编写一个命令行工具,用于处理一堆文件。我想向用户展示当前正在处理的文件,但不想让大量文件污染终端窗口。
相反,我想使用单行输出文件路径,并将该行用于下一个文件。是否有字符(或其他代码)可输出到 std::cout
以实现此目的?
另外,如果我想重新针对 Windows 调整此工具,两个平台的解决方案是否相同?
我正在为 Mac OS X 编写一个命令行工具,用于处理一堆文件。我想向用户展示当前正在处理的文件,但不想让大量文件污染终端窗口。
相反,我想使用单行输出文件路径,并将该行用于下一个文件。是否有字符(或其他代码)可输出到 std::cout
以实现此目的?
另外,如果我想重新针对 Windows 调整此工具,两个平台的解决方案是否相同?
std::cout << "will not see this\rwill see this" << std::flush;
std::cout << std::endl; // all done
int line_width = getenv("COLUMNS") ? atoi(getenv("COLUMNS")) : 80;
std::string spaces{line_width - 1, ' '};
for (const auto& filename : filenames) {
std::cout << '\r' << spaces << '\r' << filename << std::flush;
process_file(filename);
}
std::cout << std::endl; // move past last filename...
这里使用一串空格来覆盖旧文件名,然后再写入下一个文件名,因此如果您有一个较短的文件名,则不会看到早期更长文件名的尾随字符。
std::flush
确保 C++ 程序调用操作系统的 write()
函数,在开始处理文件之前将文本发送到终端。如果没有这个函数,需要更新的文本 - \r
、空格、\r
和文件名 - 将被附加到缓冲区中,并且只有在缓冲区满时才会将其写入操作系统(例如以 4k 块为单位),因此显示的文件名将落后于实际正在处理的文件数十个。此外,假设缓冲区大小为 4k - 4096 字节 - 并且在某个时刻您已经缓冲了 4080 字节,然后输出下一个文件名的文本:您将得到 \r
和 15 个空格适合缓冲区,当自动刷新时,它将擦除屏幕上行的前 15 个字符并留下先前文件名的其余部分(如果它比 15 个字符长),然后等待缓冲区再次填满才更新屏幕(仍然是杂乱无章的)。
std::endl
只是将光标移动到你已经打印文件名的行之后,这样你就可以写"all done",或者直接离开main()
,让shell提示显示在一个漂亮干净的行上,而不是潜在地覆盖你最后一个文件名的一部分(像zsh这样的好shell会检查这个问题)。
endl
之前使用flush
,因为它包含了一个隐式的flush
。实际上,只要不必立即输出,就不要使用endl
或flush
。对于换行,只需使用'\n'
。流将在最后被销毁时刷新。 - eike