LINUX 实现终端动态进度条记录

1、转义字符 \r \n 的区别

\r 代表回车,他会清空光标所在行设为数据并将该行的内容清除。

\n 代表换行,将光标移动到下一行。

2、ffush的作用

fflush刷新缓存,fflash(stdout),就是将标准输出的缓存输出并清空。

我们知道LINUX中stdout是行缓冲,啥意思,遇到换行符\n才输出缓存内容

3、动态进度条实现原理

通过一个buff 或者直接通过 printf 输出ESC 控制符设置 ,设置前景或者背景色,表示进度。

在开始输出前输出\r 将光标移动至行首并清空行。

输出完毕,调用 fflash(stdout) ,清空缓存,防止下次还输出上次的值。

3、实现

颜色控制头文件

c 复制代码
#ifndef __COLOR_H
#define __COLOR_H

//进度条使用背景色
#define COLOR_RED       "41"
#define COLOR_GREE      "42"
#define COLOR_YELLOW    "43"
#define COLOR_WHITE     "47"
//数字使用前景色
#define COLOR_RED_NUM       "31"   
#define COLOR_GREE_NUM      "32"
#define COLOR_YELLOW_NUM    "33"   
#define COLOR_WHITE_NUM     "37"   

#endif/*__COLOR_H*/

字符控制头文件

c 复制代码
#ifndef __SHOW_TYPES_H
#define __SHOW_TYPES_H




#endif/*__SHOW_TYPES_H*/

总控制头文件

c 复制代码
#ifndef __CONTROL_H
#define __CONTROL_H
//颜色头文件
#include "color.h"
#include "show_types.h"

//进度条宽度
#define BAR_WIDTH  50
#define ESC_PREFIXES    "\033["
#define ESC_SUFFIX      "m"
#define ESC_NULL        "\033[0m"
//==================================
//是否用字符表示进度条
#define USE_CHAR    1
#if USE_CHAR
//进度条 已完成部分字符
#define CONTROL_HEAD_CHAR "#"

//进度条未完成部分 字符
#define CONTROL_TAIL_CHAR " "
#endif /*#if USE_CHAR*/
//==================================

//进度条 已完成部分 颜色
#define CONTROL_HEAD_COLOR        COLOR_GREE
//进度条未完成部分 颜色
#define CONTROL_TAIL_COLOR        COLOR_WHITE


//==================================
//是否显示进度数字
#define PROGRESS__NUM     1

#if PROGRESS__NUM

#define PROGRESS__NUM_COLOR   COLOR_RED_NUM //color

#endif/*#if CONTROL_NUM*/
//==================================

源代码和测试函数

c 复制代码
#include <strings.h>
#include "control.h"
#include <unistd.h>
void show_bar(int progress,int total)
{
    char head_buff[64]={0}; //用来拼接控制字符串
    char tail_buff[64]={0}; //用来拼接控制字符串
    char num_buff[64]={0};
    int progress_num = (progress*100)/total; 
    bzero(head_buff,sizeof(head_buff));
    bzero(tail_buff,sizeof(head_buff));

    strncat(head_buff,ESC_PREFIXES,sizeof(ESC_PREFIXES));
    strncat(tail_buff,ESC_PREFIXES,sizeof(ESC_PREFIXES));
    strncat(head_buff,CONTROL_HEAD_COLOR,sizeof(CONTROL_HEAD_COLOR));
    strncat(tail_buff,CONTROL_TAIL_COLOR,sizeof(CONTROL_TAIL_COLOR));
    strncat(head_buff,ESC_SUFFIX,sizeof(ESC_SUFFIX));
    strncat(tail_buff,ESC_SUFFIX,sizeof(ESC_SUFFIX));
    #if USE_CHAR
    strncat(head_buff,CONTROL_HEAD_CHAR,sizeof(CONTROL_HEAD_CHAR));
    strncat(tail_buff,CONTROL_TAIL_CHAR,sizeof(CONTROL_TAIL_CHAR));
    #else
    strncat(head_buff," ",sizeof(" ")); 
    strncat(tail_buff," ",sizeof(" "));
    #endif
    strncat(head_buff,ESC_NULL,sizeof(ESC_NULL));
    strncat(tail_buff,ESC_NULL,sizeof(ESC_NULL));
    #if PROGRESS__NUM
    bzero(num_buff,sizeof(head_buff));
    strncat(num_buff,ESC_PREFIXES,sizeof(ESC_PREFIXES));
    strncat(num_buff,PROGRESS__NUM_COLOR,sizeof(PROGRESS__NUM_COLOR));
    strncat(num_buff,ESC_SUFFIX,sizeof(ESC_SUFFIX)); 
    #endif

    //start show
    int i;
    printf("\r[");
    for(i=0;i<BAR_WIDTH;i++)
    {
        if(i<(progress_num/(100/BAR_WIDTH)))
        {
            printf("%s",head_buff);
        }
        else
        {
            printf("%s",tail_buff);
        }
    }
    printf("]  ");
    #if PROGRESS__NUM
    printf("%s",num_buff);
    printf("%d %%",progress_num);
    printf("%s",ESC_NULL);
    #endif
    fflush(stdout);
}

int main()
{
    int i =0;
    for(i=1;i<=130;i++)
    {
        show_bar(i,130);
        usleep(5000);
    }
    printf("\n Download complete\n");
}

问题记录

1、终端作为一个进程,它的stdin\stdout\stderr缓存是怎样的?为什么终端中开启进程,进程的stdin\stdout\stderr 是直接在终端输出?这其中有什么关系?

相关推荐
獭.獭.3 分钟前
Linux -- 文件【下】
linux·服务器·文件系统·软硬链接·inode·ext2
破刺不会编程2 小时前
socket编程UDP
linux·运维·服务器·网络·c++·网络协议·udp
ayaya_mana3 小时前
Nginx性能优化与安全配置:打造高性能Web服务器
运维·nginx·安全·性能优化
NEXU58 小时前
Linux:套接字
linux·服务器·网络
我不要放纵9 小时前
docker
运维·docker·容器
morliz子轩9 小时前
基于WSL搭建Ubuntu 22.04.x LTS开发环境
linux·运维·ubuntu
BJ_Bonree10 小时前
数智先锋 | 告别运维黑盒!豪鹏科技×Bonree ONE构建全栈智能可观测体系
运维·科技
Janspran10 小时前
嵌入式linux学习 -- 进程和线程
linux·运维·学习
FreeBuf_10 小时前
CERT/CC警告:新型HTTP/2漏洞“MadeYouReset“恐致全球服务器遭DDoS攻击瘫痪
服务器·http·ddos
Cosmoshhhyyy11 小时前
linux远程部署dify和mac本地部署dify
linux·运维·macos