从文件中读取输入时创建进度条的最有效方法
Most efficient way of creating a progress bar while reading input from a file
我有一个程序,它从一个相当大的文件中读取输入,这个文件有数千行长。
话虽如此,我想在处理文件时实现一个进度条指示器。然而,我知道的大多数方法都需要使用getLine
来计算文件中有多少行,以将其用作进度条的"预定义目标"(Boost示例(。这意味着我必须在一个大文本文件中循环两次,一次是计算行数,另一次是实际获取每一行并显示进度条。
有没有更有效的方法?
一个可能的解决方案是搜索到文件的末尾,只是为了了解输入的大小。然后,根据已处理文件的百分比不断更新进度条。这将为您提供一个非常漂亮和简单的进度条——它可以用ASCII艺术和回车(\r(进行修饰。
这里还有一个可能的实现:
# include <cmath>
# include <string>
# include <fstream>
# include <iomanip>
# include <iostream>
class reader : public std::ifstream {
public:
// Constructor
template <class... Args>
inline reader(int max, Args&&... args) :
std::ifstream(args...), _max(max), _last(0) {
if (std::ifstream::is_open()) _measure();
}
// Opens the file and measures its length
template <class... Args>
inline auto open(Args&&... args)
-> decltype(std::ifstream::open(args...)) {
auto rvalue(std::ifstream::open(args...));
if (std::ifstream::is_open()) _measure();
return rvalue;
}
// Displays the progress bar (pos == -1 -> end of file)
inline void drawbar(void) {
int pos(std::ifstream::tellg());
float prog(pos / float(_length)); // percentage of infile already read
if (pos == -1) { _print(_max + 1, 1); return; }
// Number of #'s as function of current progress "prog"
int cur(std::ceil(prog * _max));
if (_last != cur) _last = cur, _print(cur, prog);
}
private:
std::string _inpath;
int _max, _length, _last;
// Measures the length of the input file
inline void _measure(void) {
std::ifstream::seekg(0, end);
_length = std::ifstream::tellg();
std::ifstream::seekg(0, beg);
}
// Prints out the progress bar
inline void _print(int cur, float prog) {
std::cout << std::fixed << std::setprecision(2)
<< "r [" << std::string(cur, '#')
<< std::string(_max + 1 - cur, ' ') << "] " << 100 * prog << "%";
if (prog == 1) std::cout << std::endl;
else std::cout.flush();
}
};
int main(int argc, char *argv[]) {
// Creating reader with display of length 100 (100 #'s)
reader infile(std::atoi(argv[2]), argv[1]);
std::cout << "-- reading file "" << argv[1] << """ << std::endl;
std::string line;
while (std::getline(infile, line)) infile.drawbar();
}
输出类似于:
$ ./reader foo.txt 50 # ./reader <inpath> <num_#'s>
-- reading file "foo.txt"
[###################################################] 100.00%
请注意,参数是输入文件和进度条中所需的#数。我已经向std::ifstream::open
函数添加了长度搜索,但drawbar()
是由用户调用的。您可以将此函数插入std::ifstream
的特定函数中。
如果你想让它更有趣,你还可以使用命令tput cols
来了解当前shell中的列数。此外,您可以将这样的命令放入可执行文件中,使其比以下更清晰:
$ ./reader foo.txt $(( $(tput cols) - 30 ))
-- reading file "foo.txt"
[####################################################################] 100.00%
正如其他人所指出的,这种解决方案无法正确处理管道和临时文件,在这种情况下,您手头没有输入长度。非常感谢@NirMH的友好评论。
相关文章:
- 有哪些有效的方法可以消除一组 100 万个字符串>重复数据?
- 在C++中初始化向量映射的最有效方法
- 将此布尔值传递给此函数的最有效方法是什么?
- 找到一种有效的方法,在 2 个巨大的缓冲区上执行 MAX,每字节字节
- 如何在工厂方法中返回指向基于基础操作系统的派生类的有效指针
- 比较C++中两个整数的最有效和最干净的方法是什么?
- 比较C++变量的最有效方法
- C++函子,有什么有效的方法吗?
- 在 c++ 中解决段树以外的范围查询的有效方法是什么?
- 存储变量的更有效方法是什么?
- 确保套装新鲜度的有效方法
- 当映射包含字符串向量作为值时,从值中获取键的有效方法
- 映射唯一值和重复值的有效方法.可以访问键或值的位置
- 在C++事务之间存储大量字符数据的有效方法
- 在unordered_multimap中精确迭代一次每个键的有效方法
- 证明两指针方法有效(对和)
- leetcode中的最大数字:有人能解释为什么这个方法有效吗
- C++ 用指针反向打印数组内容 - 为什么此方法有效
- Makefile:为什么这种自动生成先决条件的方法有效
- g++链接错误-解决方法有效的原因