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 是直接在终端输出?这其中有什么关系?

相关推荐
Zenova EdgeOS几秒前
Linux dmesg 工业边缘实战:内核日志过滤、持久化与故障定位
linux·运维·边缘计算·工业边缘·dmesg·内核日志
金士顿12 分钟前
System.Text.Json Source Generator 深度解析:为什么 Native AOT 不喜欢反射
linux·asp.net core·arm64·net·native aot
wdfk_prog1 小时前
ROS教程08:从 TransportTCP::connect() 追到 TCPROS Connection Header、序列化与 Socket 数据传输
运维·缓存·docker·容器·ros
做运维的阿瑞1 小时前
Python 标准库汇总:分类速览与常用模块清单
linux·运维·python
百万蹄蹄向前冲2 小时前
密码都对Node.js却连不上Linux数据库
linux·mysql
彧azz2 小时前
Linux 网络编程学习总结
linux·网络·笔记·学习·面试
浅念-2 小时前
Redis基础详解:单线程模型、String与Hash数据结构
服务器·数据库·redis·sql·mysql·nosql数据库·nosql
日常筹谋记2 小时前
自动化仓储安全防护工况评估:明治传感器AS-33C技术适配性分析
大数据·运维·创业创新·业界资讯
susplus3 小时前
【ARM 裸机开发 (IMX6ULL-mini)】GNU工具、Makefile 工程构建、链接脚本详解|C 语言点灯 + 蜂鸣器驱动
linux·arm·makefile·imx6ull
Shadow(⊙o⊙)3 小时前
Linux进阶知识1.0
linux·运维·服务器