Linux中实现一个简单的进度条【转】

转自:http://blog.csdn.net/yuehailin/article/details/53999288

说起进度条,其实大家常常见到,比如说你在下载视频或文件的时候,提示你当前下载进度的就是我们今天要说的进度条,进度条的模拟实现是挺简单的,但是要做的比较实用还是需要注意很多地方的,下来我就一步步的深入分析一下进度条得实现。

1.起初写下了这样的代码,解释以下几点:

    1>首先我们需要将[ ]固定在左右两边,中间预留下空间,然后用“=”进行填充。这里printf("[%-100s]\r",str);           格式化输出,‘-’表示左对齐,100表示固定列宽,然后‘\r’ 表示回车,即每次打印完使光标回到最开始位置           再明确一下,‘\n’和‘\r’这两个概念:

       ‘\n’表示换行,换到当前行的下一行,即光标指向下一行最开始的位置;'\r'指回车,即光标回到最开始位置。

    2>如果不加睡眠时间,结果一下就全打印出来了,但我们想让它稍微慢一点,毕竟是进度条嘛,而Linux系           统下默认sleep时间单位为秒(s),这样的话又觉得间隔时间太长了,于是就有了usleep,它是以微妙计的,           其头文件在#include <unistd.h>下,这些信息不明白了就man一下;

    3>如下代码我们在观察现象时会发现是隔0.1s在显示,但是它却是一段一段显示的,这就让人很是郁闷了,           最后才发现是printf的原因,printf是先将要输出的内容写到缓冲区里,然后再刷新。

 

    首先介绍一下UNIX里面关于标准IO的几种缓冲机制:

 

     <3.1>全缓冲 ,全缓冲指的是系统在填满标准IO缓冲区之后才进行实际的IO操作;注意,对于驻留在磁盘上的文件来说通常是由标准IO库实              施全缓冲。

     <3.2>行缓冲,在这种情况下,标准IO在输入和输出中遇到换行符时执行IO操作;注意,当流涉及终端的时候,通常使用的是行缓冲。

     <3.3>无缓冲,无缓冲指的是标准IO库不对字符进行缓冲存储;注意,标准出错流stderr通常是无缓冲的。

 

      printf是一个行缓冲函数,先写到缓冲区,满足条件后,才将缓冲区刷到对应文件中,刷缓冲区的条件如下:
    (1)缓冲区填满;
    (2)写入的字符中有‘\n’ ,'\r';
    (3)调用fflush手动刷新缓冲区;
    (4)调用scanf要从缓冲区中读取数据时,也会将缓冲区内的数据刷新;
    满足上面4个条件之一缓冲区就会刷新
 
下面是代码实现:

看一下效果图:

 

2.知道了上面按一段一段显示的原因,下面我们就来改进一下它,通过fflush这个函数就可以解决这个问题。

fflush用于清空缓冲流,这样就会立刻输出所有在缓冲区的内容,也就能即时刷新,这样刚好就满足了进度条的实时性。

 


下面是效果展示:


3.上面基本达到了我们想要的效果,但是还是不好,在你下载文件的时候人家就有一个百分比来提示你下载了多少了,而我们这只有一个进度条,前进了多少还得自己估计,这样多不好啊,所以我们也来实现一下这种方式。


效果图:


 

4.上面实现的看似都有了该有的效果,但是我们还是会感觉有些欠缺,比如有时候进度条会有停止不前的时候,这个时候我们很难知道程序是在继续运行还是卡住了,下面我通过一种动态旋转的图标对其进行优化。

旋转图标自己可以定,“- \ \ | /”或“| / - \ \”都可以


效果图:


 

5.最后再提一点,我在运行代码时就用了两个命令,make 和./Proc,那是因为我提前就编写了一个Makefile文件,这样就方便了我们运行代码。

下面就来看一下Makefile文件:


 

作为一个好习惯,记得每次在执行完./Proc后make clean一下

posted @ 2017-07-08 19:38  Sky&Zhang  阅读(2102)  评论(0编辑  收藏  举报