嵌入式Linux QT开发之如何实现获取磁盘空间大小的应用逻辑

简介: 嵌入式Linux QT开发之如何实现获取磁盘空间大小的应用逻辑

在Window系统上,打开我的电脑,我们就能够看见系统的每个磁盘的可用空间以及总空间,如下所示:

640.png

在嵌入式Linux与QT界面结合的产品开发中,我们在做产品的文件管理模块通常来说也需要做这样一个功能。那么如何来实现呢?

方法一:(参考QT大神-飞扬青云的磁盘容量空间控件实现)

利用Linux系统天生就已经提供的df命令来获取,例如我们可以带上-h参数,这样就可以获得以人类可读的格式显示输出,如下所示:

640.png

执行df -h以后,我们能发现一定的规律,即是输出是以行为单位输出的,并且,每一行通过空格来进行分隔标识。因此,我们能够借助QT提供的字符串分割方法以及一些简单的逻辑来实现获取其中一行的内容。


QT大佬-飞扬青云在他的磁盘容量控件里就介绍了这种方法,开源仓库:

https://gitee.com/feiyangqingyun/QWidgetDemo?_from=gitee_search

测试解析一行的函数如下:

#include "mainwindow.h"
#include "ui_mainwindow.h"
void MainWindow::Get_Disk(const QString &result, const QString &name)
{
    uint8_t index = 0;
    uint8_t percent = 0;
    QString dev, use, free, all;
    QStringList list = result.split(" ");
    for (int i = 0; i < list.count(); i++)
    {
        QString s = list.at(i).trimmed();
        if (s == "")
            continue;
        index++;
        if (index == 1)
            dev = s;
        else if (index == 2)
            all = s;
        else if (index == 3)
            use = s;
        else if (index == 4)
            free = s;
        else if (index == 5) {
            percent = s.left(s.length() - 1).toInt();
            break;
        }
    }
    if (name.length() > 0)
        dev = name;
    qDebug() << "设备名称:" << dev ;
    qDebug() << "总空间:" << all ;
    qDebug() << "已经使用了多少空间:" << use ;
    qDebug() << "剩余多少空间:" << free ;
    qDebug() << "使用的空间的百分比:" << percent << "%";
}
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    QString str = "/dev/sda4                14.4G      7.4G      7.0G  52% /mnt";
    Get_Disk(str,"/dev/sda4");
}
MainWindow::~MainWindow()
{
    delete ui;
}

运行结果:

640.png

这种方法即不需要去了解实现原理,简单来说就是一个字符串解析的过程。结合QT的QProcess函数或者Linux C提供的popen函数来调用df -h命令来获取磁盘容量信息,然后通过这种方法循环读取每一行,结合自己产品的业务逻辑去获取对应的内容即可。

方法二、直接把df命令的代码搬过来与QT进行结合

基于statfs函数实现,这种方法其实就是df命令的实现原理,statfs可以用于查询文件系统相关的信息。df命令实现如下所示:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/statfs.h>
static int ok = EXIT_SUCCESS;
//根据挂载的文件的大小来计算
static void printsize(long double n)
{
    char unit = 'K';
    n /= 1024;
    if (n > 1024) {
        n /= 1024;
        unit = 'M';
    }
    if (n > 1024) {
        n /= 1024;
        unit = 'G';
    }
    printf("%-4.1Lf%c", n, unit);
}
static void df(char *s, int always) {
    struct statfs st;
    //statfs函数可用来查询文件系统相关的信息。
    if (statfs(s, &st) < 0) {
        fprintf(stderr, "%s: %s\n", s, strerror(errno));
        ok = EXIT_FAILURE;
    } else {
        if (st.f_blocks == 0 && !always)
            return;        
        printf("%-20s  ", s);
        printsize((long double)st.f_blocks * (long double)st.f_bsize);
        printf("  ");
        printsize((long double)(st.f_blocks - (long double)st.f_bfree) * st.f_bsize);
        printf("  ");
        printsize((long double)st.f_bfree * (long double)st.f_bsize);
        printf("   %d\n", (int) st.f_bsize);
    }
}
int df_main(int argc, char *argv[]) {
    printf("Filesystem             Size   Used   Free   Blksize\n");
    if (argc == 1) {
        char s[2000];
        //挂载的文件都在/proc/mounts下显示
        FILE *f = fopen("/proc/mounts", "r");
        while (fgets(s, 2000, f)) {
            char *c, *e = s;
            for (c = s; *c; c++) {
                if (*c == ' ') {
                    e = c + 1;
                    break;
                }
            }
            for (c = e; *c; c++) {
                if (*c == ' ') {
                    *c = '\0';
                    break;
                }
            }
            df(e, 0);
        }
        fclose(f);
    } else {
        int i;
        for (i = 1; i < argc; i++) {
            df(argv[i], 1);
        }
    }
    exit(ok);
}

作为多年Ctrl-C and Ctrl-V职场老司机,想要把它融合到自己代码业务逻辑,那岂不是一件相当容易的事情?经过简单的魔改,需求就搞定了:

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <sys/vfs.h>
#include <sys/stat.h>
#include <dirent.h>
/*判断目录是否存在*/
bool dirIsExist(const char *file_path)
{
    DIR * mydir = NULL;
    if ((mydir = opendir(file_path)) == NULL)
        return false;
    closedir(mydir);
    return true;
}
/*获取磁盘的可用空间以及总空间*/
int getDiskInfo(const char *path,double * available,double *total)
{
    uint64_t blocksize;
    uint64_t totalsize;
    uint64_t availablesize;
    struct statfs diskInfo;
    if(dirIsExist(path))
        statfs(path, &diskInfo);
    else
        return -1 ;
    // 每个block里包含的字节数
    blocksize = diskInfo.f_bsize;
    // 总的字节数,f_blocks为block的数目
    totalsize = blocksize * diskInfo.f_blocks;
    // 可用空间大小
    availablesize = diskInfo.f_bavail * blocksize;
    *available = availablesize ;
    *total = totalsize ;
    return 0 ;
}
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    char av_unit = 'K';
    char total_unit = 'K';
    double availablesize = 0.00 ;
    double totalsize = 0.00 ;
    getDiskInfo("/mnt",&availablesize,&totalsize); 
    availablesize /= 1024 ;
    if(availablesize > 1024){
        availablesize /= 1024 ;
        av_unit = 'M';
    }
    if(availablesize > 1024){
        availablesize /= 1024 ;
        av_unit = 'G';
    }
    totalsize /= 1024 ;
    if(totalsize > 1024){
        totalsize /= 1024 ;
        total_unit = 'M';
    }
    if(totalsize > 1024){
        totalsize /= 1024 ;
        total_unit = 'G';
    }
    qDebug() <<"availablesize:" <<  QString("%1%2").arg(QString::number(availablesize, 'f', 1)).arg(av_unit) ;
    qDebug() <<"totalsize:" << QString("%1%2").arg(QString::number(totalsize, 'f', 1)).arg(total_unit) ;
}

在Linux下进行交叉编译后,在开发板将这个程序跑起来,运行如下:

640.png

大佬的方法简单粗暴,但个人推荐使用方法二来实现逻辑,可操作空间更大一些。下一期,我们结合iwlist以及wpa_cli来实现WIFI扫描、连接、状态查询等需求。

往期精彩

嵌入式Linux Qt应用开发WIFI搜索、显示与连接思路


嵌入式linux检测U盘拔插与QT界面开发相结合的实现思路


嵌入式QT应用开发之二维码生成


Qt串口通信接收数据不完整,怎么解决?


QT中的QMap也可以实现表驱动

目录
相关文章
|
1天前
|
编解码 Linux 5G
FFmpeg开发笔记(二十)Linux环境给FFmpeg集成AVS3解码器
AVS3,中国制定的第三代音视频标准,是首个针对8K和5G的视频编码标准,相比AVS2和HEVC性能提升约30%。uavs3d是AVS3的解码器,支持8K/60P实时解码,且在各平台有优秀表现。要为FFmpeg集成AVS3解码器libuavs3d,需从GitHub下载最新源码,解压后配置、编译和安装。之后,重新配置FFmpeg,启用libuavs3d并编译安装,通过`ffmpeg -version`确认成功集成。
10 0
FFmpeg开发笔记(二十)Linux环境给FFmpeg集成AVS3解码器
|
3天前
|
运维 监控 关系型数据库
【Zabbix 6(1),Linux运维组件化开发教程
【Zabbix 6(1),Linux运维组件化开发教程
|
5天前
|
Windows 安全 C++
Qt字符串类应用与常用基本数据类型
Qt字符串类应用与常用基本数据类型
|
5天前
|
Linux C语言
|
5天前
|
安全 Linux Android开发
FFmpeg开发笔记(十六)Linux交叉编译Android的OpenSSL库
该文介绍了如何在Linux服务器上交叉编译Android的FFmpeg库以支持HTTPS视频播放。首先,从GitHub下载openssl源码,解压后通过编译脚本`build_openssl.sh`生成64位静态库。接着,更新环境变量加载openssl,并编辑FFmpeg配置脚本`config_ffmpeg_openssl.sh`启用openssl支持。然后,编译安装FFmpeg。最后,将编译好的库文件导入App工程的相应目录,修改视频链接为HTTPS,App即可播放HTTPS在线视频。
30 3
FFmpeg开发笔记(十六)Linux交叉编译Android的OpenSSL库
|
5天前
|
Ubuntu 算法 Linux
嵌入式Linux的学习误区
该文指出了学习嵌入式Linux开发的两个常见误区。一是过分专注于学习桌面或服务器版Linux,而非关注嵌入式开发本身,实际上只需熟悉基本操作即可。二是试图在没有基础的情况下直接阅读Linux内核源代码,这是不切实际的,应先建立基础知识再进行源码学习。文章还提到了在嵌入式系统中获取和处理屏幕数据的示例,包括使用gsnap工具将framebuffer数据转为图像,以及涉及的交叉编译过程。
11 0
|
5天前
|
前端开发 Linux iOS开发
【Flutter前端技术开发专栏】Flutter在桌面应用(Windows/macOS/Linux)的开发实践
【4月更文挑战第30天】Flutter扩展至桌面应用开发,允许开发者用同一代码库构建Windows、macOS和Linux应用,提高效率并保持平台一致性。创建桌面应用需指定目标平台,如`flutter create -t windows my_desktop_app`。开发中注意UI适配、性能优化、系统交互及测试部署。UI适配利用布局组件和`MediaQuery`,性能优化借助`PerformanceLogging`、`Isolate`和`compute`。
【Flutter前端技术开发专栏】Flutter在桌面应用(Windows/macOS/Linux)的开发实践
|
6月前
|
消息中间件 缓存 Unix
[面试必备]嵌入式Linux内核开发必须了解的三十道题
[面试必备]嵌入式Linux内核开发必须了解的三十道题
|
11月前
|
Linux Go 人机交互
嵌入式linux之go语言开发(十三)LittlevGL,漂亮的嵌入式GUI的go语言绑定
嵌入式linux之go语言开发(十三)LittlevGL,漂亮的嵌入式GUI的go语言绑定
|
11月前
|
存储 XML JSON
嵌入式linux之go语言开发(十二)参数配置文件存储模块开发
嵌入式linux之go语言开发(十二)参数配置文件存储模块开发

热门文章

最新文章