Qt文件操作:QFile与QTextStream全解析

3.3 文件操作类 QFile
QFile Qt 框架中用于文件处理的一个类。它提供了读取和写入文件的功能,支持文本和二进制文
件。
QFile 继承自 QIODevice ,因此它可以像其他IO设备一样使用。
主要功能
1. 文件读写QFile 支持打开文件进行读取或写入操作
2. 文件信息:可以检索有关文件的信息,如大小、修改日期等。
3. 文件操作:提供了对文件进行重命名、移动、删除等操作的能力。
4. 错误处理QFile 在操作文件时提供了错误处理机制,可以通过相应的函数检查和获取错误信息。
常用方法
open() :打开一个文件。需要指定模式(如只读、只写、读写等)。
close() :关闭文件。
read() write() :用于读取和写入数据。
exists() :检查文件是否存在。
remove() :删除文件。
copy() :复制文件。
示例代码
以下是使用 QFile 的一个简单例子:
#include "widget.h"
#include "ui_widget.h"
#include <QFile>
#include <QDebug>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
}
Widget::~Widget()
{
delete ui;
}
void Widget::on_btnRead_clicked()
{
//1. 打开文件
//QFile file("D:/QT/test.txt");
QFile file;
file.setFileName("D:/QT/test.txt");
if(!file.open(QIODevice::ReadOnly | QIODevice::Text)){
qDebug() << "file open error";
}
//2. 读取文件
char context[100] = {'\0'};
if( file.read(context,100) == -1) return;
//3. 输出文件内容
qDebug() << context;
file.close();
}
void Widget::on_btnWrite_clicked()
{
// 1.打开
QFile file("D:/QT/test2.txt");
file.open(QIODevice::WriteOnly | QIODevice::Text);
// 2. 写入
file.write("Program 45-QFile001 write something to This File 我是老陈");
// 3. 关闭
file.close();
}
3.3.3 QTextStream
QTextStream 的主要特性成一个表格。请看下表:
TextStream 是一个功能强大的类,用于处理文本数据,特别是在需要考虑字符编码和文本格式化的情
况下。通过这些特性,它提供了一种灵活而强大的方式来读写和操作文本。
使用示例
以下是一个更详细的示例,展示了如何使用 QTextStream 来读写文件:
void Widget::on_btnstrRead_clicked()
{
QFile file;
file.setFileName("D:/QT/test.txt");
if(!file.open(QIODevice::ReadOnly | QIODevice::Text)){
qDebug() << "file open error";
}
QTextStream in(&file);
in.setCodec("UTF-8");
// QString context = in.read(file.size());
while(!in.atEnd()){
QString context = in.readLine();
qDebug() << context;
}
file.close();
}
void Widget::on_btnstreamWrite_clicked()
{
QFile file;
file.setFileName("D:/QT/test3.txt");
if(!file.open(QIODevice::WriteOnly | QIODevice::Text)){
qDebug() << "file open error";
}
QTextStream out(&file);
out.setCodec("UTF-8");
out << "I write stream char to File";
file.close();
}
#include "widget.h"
#include "ui_widget.h"

#include <QFile>

Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{
    ui->setupUi(this);
//    connect(this, SIGNAL(mysignal()), this, SLOT(myslot()));
//    connect(this, SIGNAL(mysignalparams(int)), this, SLOT(myslotparams(int)));
//    emit mysignal();
//    emit mysignalparams(100);
}

Widget::~Widget()
{
    delete ui;
}

//void Widget::myslot()
//{
//    std::cout << "myslot" << std::endl;
//}

//void Widget::myslotparams(int value)
//{
//    qDebug() << "myslotparams";
//    qDebug() << value;
//}


void Widget::on_btnRead_clicked()
{
//    QFile file("E:/QT2/test.txt");
      QFile file;
      file.setFileName("E:/QT/test.txt");
    if(!file.open(QIODevice::ReadOnly | QIODevice::Text)){
        qDebug() << "file open error";
    }
    int size = file.size();
    char* context = new char(size);
    char* con = (char *)malloc(sizeof(char)*size);
//    char context[100] = {"\0"};
    if(file.read(context, 100) == -1) return;
    qDebug() << context;
    file.close();
}


void Widget::on_btnWrite_clicked()
{
    QFile file("E:/QT/test2.txt");
    file.open(QIODevice::WriteOnly | QIODevice::Text);
    file.write("Program 45-QFile001 write something to This File 我是测试");
}


void Widget::on_btnstreamRead_clicked()
{
    QFile file;
    file.setFileName("E:/QT/test.txt");
  if(!file.open(QIODevice::ReadOnly | QIODevice::Text)){
      qDebug() << "file open error";
  }

    QTextStream in(&file);
    in.setCodec("UTF-8");
    //QString context = in.read(file.size());
    while(!in.atEnd()){
    QString context = in.readLine();
    qDebug() << context;
    qDebug() << "---------";
    }

    file.close();
}


void Widget::on_btnstreamWrite_clicked()
{
    QFile file;
    file.setFileName("E:/QT/test3.txt");
  if(!file.open(QIODevice::WriteOnly | QIODevice::Text)){
      qDebug() << "file open error";
  }
    QTextStream out(&file);
    out.setCodec("UTF-8");
    out << "I write stream char to file ";
    file.close();
}

//解释这串代码,写上注释

这段代码是一个 Qt 项目的 widget.cpp 文件,实现了基于文件操作的功能。它通过按钮点击事件调用不同的槽函数,分别实现 读取文本文件、写入文本文件、以流方式读写文件 的功能。

下面我将为你逐行添加详细的中文注释,并解释每个函数的作用和实现逻辑。


📁 包含头文件


cpp

深色版本

#include "widget.h"
#include "ui_widget.h"     // 自动生成的 UI 类定义(包含界面控件)
#include <QFile>           // Qt 提供的用于文件操作的类

🔧 构造函数和析构函数


cpp

深色版本

// 构造函数:初始化窗口部件
Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{
    ui->setupUi(this);  // 初始化由 .ui 文件生成的界面控件
}

// 析构函数:释放资源
Widget::~Widget()
{
    delete ui;  // 删除 UI 对象
}

📖 按钮点击事件处理函数

✅ 1. on_btnRead_clicked() —— 使用字节方式读取文件内容


cpp

深色版本

void Widget::on_btnRead_clicked()
{
    QFile file;
    file.setFileName("E:/QT/test.txt");  // 设置要打开的文件路径

    // 尝试以只读+文本模式打开文件
    if(!file.open(QIODevice::ReadOnly | QIODevice::Text)){
        qDebug() << "file open error";  // 打开失败,输出错误信息
        return;
    }

    int size = file.size();  // 获取文件大小(字节数)

    // 分配内存空间来存储读取的内容
    char* context = new char(size);  // 动态分配内存
    char* con = (char *)malloc(sizeof(char)*size);  // C风格内存分配(未使用)

    // 从文件中读取最多100个字节到 context 缓冲区
    if(file.read(context, 100) == -1) {
        qDebug() << "read error";
        return;
    }

    qDebug() << context;  // 输出读取到的内容到调试控制台

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

    // 建议:记得在最后释放动态分配的内存
    delete[] context;
    free(con);
}

📌 注意问题

  • new char(size) 只分配了一个字符的空间,而不是字符串长度。应为:new char[size]
  • 推荐使用 QByteArray 或 QString 来避免手动管理内存。

✅ 2. on_btnWrite_clicked() —— 写入文本文件


cpp

深色版本

void Widget::on_btnWrite_clicked()
{
    // 创建并打开一个文件用于写入
    QFile file("E:/QT/test2.txt");

    // 以只写+文本模式打开文件(若文件不存在会自动创建)
    if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
        qDebug() << "file open error";
        return;
    }

    // 向文件中写入字符串
    file.write("Program 45-QFile001 write something to This File 我是测试");

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

📌 说明

  • 如果文件已存在,原内容会被清空;
  • 如果只想追加内容,请使用 QIODevice::Append 模式。

✅ 3. on_btnstreamRead_clicked() —— 使用 QTextStream 流方式读取文件


cpp

深色版本

void Widget::on_btnstreamRead_clicked()
{
    QFile file;
    file.setFileName("E:/QT/test.txt");  // 设置文件路径

    // 以只读+文本模式打开文件
    if(!file.open(QIODevice::ReadOnly | QIODevice::Text)){
        qDebug() << "file open error";
        return;
    }

    // 创建 QTextStream 对象,用于按流的方式读取文件
    QTextStream in(&file);

    // 设置编码格式为 UTF-8(支持中文)
    in.setCodec("UTF-8");

    // 逐行读取直到文件结尾
    while(!in.atEnd()){
        QString context = in.readLine();  // 读取一行内容
        qDebug() << context;              // 输出到调试控制台
        qDebug() << "---------";          // 分隔线
    }

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

📌 优点

  • 支持中文;
  • 更适合读取文本文件;
  • 可以设置编码格式(如 UTF-8)。

✅ 4. on_btnstreamWrite_clicked() —— 使用 QTextStream 流方式写入文件


cpp

深色版本

void Widget::on_btnstreamWrite_clicked()
{
    QFile file;
    file.setFileName("E:/QT/test3.txt");  // 设置目标文件路径

    // 以只写+文本模式打开文件
    if(!file.open(QIODevice::WriteOnly | QIODevice::Text)){
        qDebug() << "file open error";
        return;
    }

    // 创建 QTextStream 对象,用于流式写入
    QTextStream out(&file);

    // 设置编码格式为 UTF-8(支持中文)
    out.setCodec("UTF-8");

    // 写入字符串内容
    out << "I write stream char to file ";

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

📌 说明

  • 使用 << 运算符可以像 std::cout 一样写入数据;
  • 支持多语言(中文);
  • 写入前文件内容会被清空。

📌 总结:功能一览

函数名功能描述
on_btnRead_clicked()以字节形式读取文件内容(不推荐手动管理内存)
on_btnWrite_clicked()写入指定文本到文件
on_btnstreamRead_clicked()使用 QTextStream 读取文本文件(推荐)
on_btnstreamWrite_clicked()使用 QTextStream 写入文本文件(推荐)

✅ 推荐改进点

改进项建议
内存管理避免手动 new/delete,改用 QByteArray 或 QString
文件路径使用相对路径或让用户选择文件(如 QFileDialog
异常处理添加更完善的错误提示机制
字符串编码始终设置 setCodec("UTF-8"),避免中文乱码
文件关闭确保每次操作后都 close() 文件
日志输出使用 qDebug() 而不是 std::cout

如果你希望我帮你补充文件选择对话框(QFileDialog)、支持更多编码格式、或者把内容显示在界面上(如 QTextEdit),也可以继续提问 😊

#ifndef WIDGET_H
#define WIDGET_H

#include<iostream>
#include <QWidget>
#include<QDebug>

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

//signals:
//        void mysignal();
//        void mysignalparams(int value);
//private slots:
//        void myslot();
//        void myslotparams(int value);


private slots:
    void on_btnRead_clicked();

    void on_btnWrite_clicked();

    void on_btnstreamRead_clicked();

    void on_btnstreamWrite_clicked();

private:
    Ui::Widget *ui;
};
#endif // WIDGET_H
//解释这串代码,写上注释

这段代码是 widget.h 文件,它是 Qt 项目中一个自定义窗口部件类的头文件。它声明了一个名为 Widget 的类,继承自 QWidget,并定义了几个槽函数(slots),用于响应界面上按钮的点击事件。


📄 逐行解释与中文注释


cpp

深色版本

#ifndef WIDGET_H
#define WIDGET_H
  • 头文件卫士(Header Guard)
    • 防止该头文件被多次包含,避免重复定义类或变量。
    • 如果 WIDGET_H 没有被定义,则继续编译下面的内容;
    • 否则跳过整个文件。

cpp

深色版本

#include <iostream>
#include <QWidget>
#include <QDebug>
  • 引入必要的头文件:
    • <iostream>:C++ 标准输入输出流,可用于 std::cout
    • <QWidget>:Qt 提供的基础 GUI 类,所有界面控件都基于此类;
    • <QDebug>:Qt 提供的调试输出工具,比 std::cout 更适合 Qt 程序使用。

cpp

深色版本

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE
  • Qt 使用的命名空间宏:
    • namespace Ui { class Widget; } 是对由 .ui 文件生成的 UI 类的前置声明;
    • 实际上,.ui 文件会被 Qt Designer 转换为 ui_widget.h 文件,在运行时通过 ui->xxx 来访问界面上的控件。

cpp

深色版本

class Widget : public QWidget
{
    Q_OBJECT
  • 定义一个名为 Widget 的类,继承自 QWidget
  • Q_OBJECT 是 Qt 的宏,表示这个类支持以下功能:
    • 信号与槽机制(Signal-Slot)
    • 元对象系统(Meta Object)
    • 动态属性、国际化等特性

cpp

深色版本

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();
  • 构造函数和析构函数:
    • Widget(QWidget *parent = nullptr):构造函数,可接受父窗口指针,默认为 nullptr
    • ~Widget():析构函数,释放资源(如 UI 指针);

cpp

深色版本

//signals:
//        void mysignal();
//        void mysignalparams(int value);
//private slots:
//        void myslot();
//        void myslotparams(int value);
  • 这些是之前定义但被注释掉的信号与槽函数
    • mysignal() 和 mysignalparams(int) 是自定义信号;
    • myslot() 和 myslotparams(int) 是对应的槽函数;
  • 注释掉意味着当前不使用这些信号/槽。

cpp

深色版本

private slots:
    void on_btnRead_clicked();

    void on_btnWrite_clicked();

    void on_btnstreamRead_clicked();

    void on_btnstreamWrite_clicked();
  • 声明四个私有槽函数,它们将响应界面上按钮的点击事件:
    • on_btnRead_clicked():读取文件内容;
    • on_btnWrite_clicked():写入文件内容;
    • on_btnstreamRead_clicked():以流方式读取文件;
    • on_btnstreamWrite_clicked():以流方式写入文件;
  • 函数名格式为 on_<objectName>_<signalName>(),这是 Qt 的自动连接机制要求的命名方式;
    • 例如:如果有一个按钮的 objectName 是 btnRead,它的 clicked() 信号会自动绑定到 on_btnRead_clicked()

cpp

深色版本

private:
    Ui::Widget *ui;
  • 私有成员变量:
    • Ui::Widget *ui:指向由 .ui 文件生成的界面类的指针;
    • 通过 ui->控件名 可以访问界面上的按钮、标签等控件。

cpp

深色版本

#endif // WIDGET_H
  • 结束头文件卫士,与最开始的 #ifndef WIDGET_H 配套使用。

✅ 总结结构图

部分内容
头文件卫士#ifndef / #define / #endif
引入头文件<iostream><QWidget><QDebug>
UI 前置声明namespace Ui { class Widget; }
类定义class Widget : public QWidget
支持 Qt 特性Q_OBJECT 宏
构造/析构函数初始化窗口、释放资源
槽函数四个按钮点击事件处理函数
UI 成员指针Ui::Widget *ui;,用于操作界面控件

💡 小贴士

  • 不要手动删除或修改 ui->setupUi(this);,这是加载 .ui 文件的关键语句;
  • 所有以 on_控件名_信号名() 命名的函数都会被 Qt 自动连接;
  • 如果你添加了新的按钮并想让其触发某个函数,请确保:
    • 控件名(objectName)正确;
    • 函数名格式匹配;
    • 在 .h 中声明为 private slots:
    • 在 .cpp 中实现该函数。

如果你还需要我帮你补充完整 .cpp 文件内容,或者演示如何在界面上显示文件内容(比如用 QTextEdit),也可以继续提问 😊

wight.h和wight.cpp有什么关系和区别?

在C++编程中,.h文件(通常称为头文件)和.cpp文件(源文件)有着不同的角色和用途。以你提到的widget.hwidget.cpp为例,我们可以解释它们之间的关系和区别:

头文件(widget.h

  1. 声明:头文件主要用于声明类、函数、变量以及包含其他必要的头文件。它定义了接口或合约,但不提供具体的实现细节。
  2. 包含保护:为了避免重复包含导致的编译错误,头文件通常会有预处理指令(如#ifndef#define#endif)来防止多次包含。
  3. 依赖管理:通过头文件,你可以声明依赖而不必暴露实现细节。这有助于模块化设计,减少耦合。

源文件(widget.cpp

  1. 实现:源文件包含了与头文件中声明对应的实现代码。也就是说,在这里你会找到所有函数的具体实现,包括成员函数的定义、全局函数等。
  2. 隐藏实现细节:将实现放在.cpp文件中可以隐藏内部工作原理,只对外公开必要的接口。这对于库开发者来说尤其重要,因为他们可能不想让用户知道或者修改内部实现。
  3. 独立编译:每个.cpp文件可以单独编译成目标文件(object file),然后由链接器将这些目标文件链接在一起形成最终的可执行程序。

关系

  • 对应性:一个.cpp文件通常会对应一个.h文件,尽管这不是强制性的。例如,widget.cpp实现了widget.h中声明的所有函数和方法。
  • #include:在.cpp文件中,通常会使用#include指令引入相应的.h文件,这样编译器就知道如何解析该源文件中的符号(如类、函数等)。

区别

  • 功能不同.h文件主要负责声明,而.cpp文件负责实现。
  • 编译过程不同.cpp文件会被编译为对象文件,而.h文件则不会直接参与编译过程,而是被其他源文件通过#include指令包含进来。

总之,widget.hwidget.cpp是相辅相成的,前者提供了类的蓝图,后者则是这个蓝图的具体实现。这种分离有助于提高代码的可维护性和重用性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小范好好学习

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值