QT-系统(文件)

目录

记事本模拟

需求与技术选型

界面搭建:菜单与编辑区的组合

[文件 "打开" 功能:从路径选择到内容读取](#文件 “打开” 功能:从路径选择到内容读取)

[文件 "保存" 功能:从内容获取到文件写入](#文件 “保存” 功能:从内容获取到文件写入)

[QIODevice 家族与文件操作的扩展性](#QIODevice 家族与文件操作的扩展性)

总结与拓展

获取文件属性

[QFileInfo 是什么?](#QFileInfo 是什么?)

[QFileInfo 常用方法解析](#QFileInfo 常用方法解析)

[实战:用 QFileInfo 解析文件属性](#实战:用 QFileInfo 解析文件属性)

场景:选择文件后,打印其元信息

代码说明

总结


记事本模拟

在 Qt 开发中,文件操作和界面交互是非常基础且重要的能力。本文将通过打造一个简易记事本应用,带你深入理解 Qt 中如何实现文件的 "打开""保存" 功能,以及界面组件的联动逻辑。我们会基于 QIODevice 家族的 QFile 类来完成文件 IO,同时结合 QAction、QPlainTextEdit 等组件构建交互界面。

需求与技术选型

我们要实现的记事本功能很明确:

  • 界面上有 "文件" 菜单,包含 "打开""保存" 两个操作选项;
  • 支持通过文件对话框选择文件,读取文件内容到编辑区;
  • 支持将编辑区内容保存到指定文件。

技术选型

  • 界面框架:Qt 的 QMainWindow + QMenuBar + QPlainTextEdit,构建经典窗口应用结构;
  • 文件操作:QFile(属于 QIODevice 家族,用于本地文件读写)+ QFileDialog(文件选择对话框);
  • 事件联动:QAction + 信号槽机制,实现菜单操作与业务逻辑的绑定。

界面搭建:菜单与编辑区的组合

首先,我们需要构建应用的界面骨架 ------ 包含菜单的菜单栏,以及用于编辑文本的输入区域。

cpp 复制代码
// mainwindow.cpp 构造函数部分
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    this->setWindowTitle("记事本"); // 设置窗口标题

    // 1. 构建菜单栏与菜单
    QMenuBar* menubar = this->menuBar();
    QMenu* menu = new QMenu("文件");
    menubar->addMenu(menu);

    // 2. 构建"打开""保存"动作(QAction)
    QAction* a1 = new QAction("打开");
    QAction* a2 = new QAction("保存");
    menu->addAction(a1);
    menu->addAction(a2);

    // 3. 构建文本编辑区
    edit = new QPlainTextEdit();
    QFont font;
    font.setPixelSize(20); // 设置字体大小,提升可读性
    edit->setFont(font);
    this->setCentralWidget(edit); // 将编辑区设为窗口中心组件

    // 4. 信号槽绑定:动作触发时执行对应的业务函数
    connect(a1, &QAction::triggered, this, &MainWindow::handleAction1);
    connect(a2, &QAction::triggered, this, &MainWindow::handleAction2);
}

这段代码的核心是组件的分层组织:菜单栏作为顶层导航,文本编辑区作为内容载体,通过 QAction 把 "菜单点击" 和 "文件操作逻辑" 关联起来(信号槽机制的经典应用)。

文件 "打开" 功能:从路径选择到内容读取

"打开文件" 功能的流程是:选择文件路径 → 打开文件 → 读取内容 → 展示到编辑区 。我们通过 QFileDialog 选路径,QFile 做读写,步骤清晰且容错性强。

cpp 复制代码
void MainWindow::handleAction1()
{
    // 1. 弹出"打开文件"对话框,让用户选择文件
    QString path = QFileDialog::getOpenFileName(this);
    if (path.isEmpty()) return; // 用户取消选择,直接返回

    // 2. 把选中的文件路径显示到状态栏,方便用户确认
    QStatusBar* statusBar = this->statusBar();
    statusBar->showMessage("正在打开:" + path);

    // 3. 构造 QFile 对象并尝试打开(只读模式)
    QFile file(path);
    bool ret = file.open(QIODevice::ReadOnly);
    if (!ret) {
        // 打开失败时给用户提示
        statusBar->showMessage(path + " 打开失败!");
        return;
    }

    // 4. 读取文件全部内容
    QString text = file.readAll();

    // 5. 关闭文件(必须!否则会导致文件占用等问题)
    file.close();

    // 6. 将读取的内容设置到文本编辑区
    edit->setPlainText(text);
    statusBar->showMessage(path + " 打开成功!");
}

关键细节

  • QFileDialog::getOpenFileName 会弹出系统原生的文件选择框,用户选择后返回文件路径;
  • QFile::open 要指定打开模式(这里是 ReadOnly 只读),打开失败时需给用户明确提示;
  • 读取完成后必须关闭文件,否则会造成资源泄漏或文件异常。

文件 "保存" 功能:从内容获取到文件写入

"保存文件" 的流程是:选择保存路径 → 打开文件 → 写入内容 → 关闭文件。和 "打开" 逻辑对称,但要注意写入模式的选择。

cpp 复制代码
void MainWindow::handleAction2()
{
    // 1. 弹出"保存文件"对话框,让用户选择保存路径
    QString path = QFileDialog::getSaveFileName(this);
    if (path.isEmpty()) return; // 用户取消选择,直接返回

    // 2. 把保存路径显示到状态栏
    QStatusBar* statusBar = this->statusBar();
    statusBar->showMessage("正在保存:" + path);

    // 3. 构造 QFile 对象并尝试打开(只写模式)
    QFile file(path);
    bool ret = file.open(QFile::WriteOnly);
    if (!ret) {
        statusBar->showMessage(path + " 打开失败!");
        return;
    }

    // 4. 获取编辑区的文本内容,并写入文件
    const QString& text = edit->toPlainText();
    file.write(text.toUtf8()); // 转成 UTF-8 编码写入,避免中文乱码

    // 5. 关闭文件
    file.close();

    statusBar->showMessage(path + " 保存成功!");
}

关键细节

  • QFileDialog::getSaveFileName 会处理 "文件不存在则创建" 的逻辑,无需手动判断;
  • 写入时用 WriteOnly 模式,若文件已存在会覆盖原有内容(如需追加可改用 Append 模式);
  • 文本编码要统一(这里用 toUtf8() 转 UTF-8),否则可能出现中文乱码。

QIODevice 家族与文件操作的扩展性

在 Qt 中,QFileQIODevice 的子类,而 QIODevice 是所有 IO 设备的抽象基类,它还包含了 QTcpSocket(网络套接字)、QBuffer(内存缓冲区)等子类。

这意味着我们的文件操作逻辑具有很强的扩展性 ------ 如果未来需要把 "记事本" 的内容通过网络发送(比如做一个 "云记事本"),只需把 QFile 替换成 QTcpSocket,底层的 openreadAllwrite 等接口可以无缝兼容。这种面向抽象类编程的设计,是 Qt 框架灵活性的体现。

总结与拓展

通过这个简易记事本的实现,我们掌握了 Qt 中界面构建、文件 IO、信号槽联动的核心流程:

  • 界面层:用 QMenuBarQAction 构建交互入口,QPlainTextEdit 承载内容;
  • 逻辑层:用 QFile + QFileDialog 完成本地文件的 "打开""保存",并通过状态栏给用户反馈;
  • 架构层:借助 QIODevice 的抽象设计,为功能扩展留下了空间。

获取文件属性

在 Qt 开发中,操作文件时不仅需要读写内容,还经常需要获取文件的元信息(如文件名、大小、类型、修改时间等)。Qt 提供的 QFileInfo 类就是为解决这个需求而生的,它可以让我们便捷地获取文件和目录的各种属性。本文将带你深入了解 QFileInfo 的常用方法和实际应用场景。

QFileInfo 是什么?

QFileInfo 是 Qt 框架中专门用于获取文件和目录信息的类。它可以帮助我们查询文件的文件名、大小、类型、创建时间、修改时间等元数据,让文件操作更加灵活和智能。

无论是普通文件还是目录,QFileInfo 都能轻松应对,是文件管理类应用(如文件浏览器、资源管理器)和需要文件元信息的业务场景(如日志分析、资源统计)的得力工具。

QFileInfo 常用方法解析

QFileInfo 提供了丰富的方法来获取文件的各种属性,以下是最常用的几个:

方法名 功能说明
isDir() 检查当前路径是否是目录
isExecutable() 检查文件是否是可执行文件
fileName() 获取文件名(不含路径)
completeBaseName() 获取完整的文件名(不含后缀)
suffix() 获取文件后缀名(如 "txt"、"exe")
completeSuffix() 获取完整的文件后缀(复杂后缀场景,如 "tar.gz")
size() 获取文件大小(字节数)
isFile() 判断是否是普通文件(非目录)
fileTime() 获取文件的创建时间、修改时间、最近访问时间等

实战:用 QFileInfo 解析文件属性

下面我们通过一个简单的示例,演示如何用 QFileInfo 获取并打印文件的各项属性。

场景:选择文件后,打印其元信息

我们通过 QFileDialog 让用户选择一个文件,然后用 QFileInfo 解析它的属性并打印。

cpp 复制代码
void Widget::on_pushButton_clicked()
{
    // 弹出文件选择对话框,让用户选择一个文件
    QString path = QFileDialog::getOpenFileName(this);
    if (path.isEmpty()) { // 用户取消选择,直接返回
        return;
    }

    // 构造 QFileInfo 对象,传入文件路径
    QFileInfo fileInfo(path);

    // 打印文件的各项属性
    qDebug() << "文件名:" << fileInfo.fileName();
    qDebug() << "文件后缀:" << fileInfo.suffix();
    qDebug() << "文件路径:" << fileInfo.path();
    qDebug() << "文件大小:" << fileInfo.size() << "字节";
    qDebug() << "是否为文件:" << fileInfo.isFile();
    qDebug() << "是否为目录:" << fileInfo.isDir();
    qDebug() << "是否可执行:" << fileInfo.isExecutable();
    qDebug() << "创建时间:" << fileInfo.fileTime(QFileInfo::CreationTime);
    qDebug() << "修改时间:" << fileInfo.fileTime(QFileInfo::ModificationTime);
}

代码说明

  1. 文件选择 :通过 QFileDialog::getOpenFileName 弹出文件选择框,获取用户选择的文件路径。
  2. 构造 QFileInfo :将文件路径传入 QFileInfo 构造函数,创建文件信息对象。
  3. 属性查询与打印 :通过 QFileInfo 的各种方法,分别获取文件名、后缀、路径、大小、类型、时间等信息,并通过 qDebug() 打印。

总结

QFileInfo 是 Qt 中处理文件元信息的 "瑞士军刀",它让我们摆脱了底层系统 API 的繁琐调用,以面向对象的方式轻松获取文件的各种属性。无论是简单的文件信息打印,还是复杂的文件类型校验、目录遍历,QFileInfo 都能提供简洁高效的解决方案。

相关推荐
Scott9999HH4 小时前
【IIoT流量实战】蒸汽管道阀门全关却仍有流量?用 Python 实现涡街信号 FFT 频谱分析与温压全补偿积算网关,深度拆解靠谱的涡街流量计厂家硬核技术标准
开发语言·python
码智社5 小时前
AES加密原理详解及Java实现加解密实战
java·开发语言
AI云海5 小时前
python 列表、元组、集合和字典
开发语言·python
萧瑟余晖6 小时前
JDK 26 新特性详解
java·开发语言
马优晨6 小时前
Freemarker 完整讲解(后端 Java 模板引擎)
java·开发语言·freemarker·freemarker 完整讲解·freemarker模板引擎
人邮异步社区8 小时前
怎么把C语言学到精通?
c语言·开发语言
心平气和量大福大9 小时前
C#-WPF-控件-TextBox 数据绑定
开发语言·c#·wpf
ttwuai9 小时前
Cursor 生成 CRUD 后,Go 后台接口别只测 200:JWT、RBAC 和 tenant_id 怎么验
开发语言·后端·golang
এ慕ོ冬℘゜9 小时前
前端基础:什么是时间戳?JS获取时间戳三种方法与实战用途
开发语言·前端·javascript
执明wa9 小时前
LayoutInflater详解: XML是如何变成View的?
android·xml·开发语言·android studio