嵌入式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也可以实现表驱动

目录
相关文章
|
2月前
|
存储 监控 安全
在Linux中,⼀个EXT3的文件分区,当使用touch test.file命令创建⼀个新文件时报错,报错的信息是提示磁盘已满,但是采用df -h命令查看磁盘大小时,只使用了,60%的磁盘空间,为什么会出现这个情况?
在Linux中,⼀个EXT3的文件分区,当使用touch test.file命令创建⼀个新文件时报错,报错的信息是提示磁盘已满,但是采用df -h命令查看磁盘大小时,只使用了,60%的磁盘空间,为什么会出现这个情况?
|
4天前
|
开发工具 C++
qt开发技巧与三个问题点
本文介绍了三个Qt开发中的常见问题及其解决方法,并提供了一些实用的开发技巧。
|
1月前
|
2月前
|
C++
C++ Qt开发:QUdpSocket网络通信组件
QUdpSocket是Qt网络编程中一个非常有用的组件,它提供了在UDP协议下进行数据发送和接收的能力。通过简单的方法和信号,可以轻松实现基于UDP的网络通信。不过,需要注意的是,UDP协议本身不保证数据的可靠传输,因此在使用QUdpSocket时,可能需要在应用层实现一些机制来保证数据的完整性和顺序,或者选择在适用的场景下使用UDP协议。
75 2
|
2月前
|
NoSQL Linux C语言
嵌入式GDB调试Linux C程序或交叉编译(开发板)
【8月更文挑战第24天】本文档介绍了如何在嵌入式环境下使用GDB调试Linux C程序及进行交叉编译。调试步骤包括:编译程序时加入`-g`选项以生成调试信息;启动GDB并加载程序;设置断点;运行程序至断点;单步执行代码;查看变量值;继续执行或退出GDB。对于交叉编译,需安装对应架构的交叉编译工具链,配置编译环境,使用工具链编译程序,并将程序传输到开发板进行调试。过程中可能遇到工具链不匹配等问题,需针对性解决。
|
2月前
|
Ubuntu Linux 测试技术
在Linux中,已知 apache 服务的访问日志按天记录在服务器本地目录/app/logs 下,由于磁盘空间紧张现在要求只能保留最近7天的访问日志,请问如何解决?
在Linux中,已知 apache 服务的访问日志按天记录在服务器本地目录/app/logs 下,由于磁盘空间紧张现在要求只能保留最近7天的访问日志,请问如何解决?
|
2月前
|
Linux API
在Linux中,程序产生了库日志虽然删除了,但磁盘空间未更新是什么原因?
在Linux中,程序产生了库日志虽然删除了,但磁盘空间未更新是什么原因?
|
2月前
|
网络协议 容器
Qt开发网络嗅探器03
Qt开发网络嗅探器03
|
2月前
|
传感器 人工智能 网络协议
:嵌入式 Linux 及其用途
【8月更文挑战第24天】
89 0
|
2月前
|
API 开发工具 C语言
C语言与图形界面:利用GTK+、Qt等库创建GUI应用。
C语言与图形界面:利用GTK+、Qt等库创建GUI应用。
82 0
下一篇
无影云桌面