文件操作和文件读写
- QFile 类用于对文件进行操作,它继承自 QIODevice,可以进行读写操作。主要用于打开、关闭、读取、写入和管理文件。
1. 首先要指定文件路径
- QFile fn(“文件路径”);
- 也可以通过文件对话框来选择文件getOpenFileName
函数原型
QString QFileDialog::getOpenFileName(QWidget *parent = nullptr,const QString &caption = tr("Open File"),const QString &dir = QString(),const QString &filter = QString(),QString *selectedFilter = nullptr,QFileDialog::Option options = QFileDialog::Options()
);
代码举例
QString fn = QFileDialog::getOpenFileName(this,"openFile","/home/QFile","*.txt;;*.h *.c");
2. 指定文件打开权限,即打开之后能够操作什么
-
假设已经给fn指定好路径了,那么则有fn.open(权限)
-
文件打开权限
函数 | 值 | 描述 |
---|---|---|
QIODevice::NotOpen | 0x0000 | 未打开模式。文件没有被打开。 |
QIODevice::ReadOnly | 0x0001 | 只读模式。文件被打开以进行读取操作。 |
QIODevice::WriteOnly | 0x0002 | 只写模式。文件被打开以进行写入操作。 |
QIODevice::ReadWrite | 0x0003 | 读写模式。文件被打开以进行读取和写入操作。 |
QIODevice::Append | 0x0004 | 追加模式。文件被打开以在末尾追加数据,不会覆盖原有内容。 |
QIODevice::Truncate | 0x0008 | 截断模式。如果文件存在,将清空文件内容。 |
QIODevice::Text | 0x0010 | 文本模式。以文本模式打开文件,行结束符会自动转换为系统特定的格式(例如\n 在Unix/Linux系统中,\r\n 在Windows系统中)。 |
QIODevice::Unbuffered | 0x0040 | 无缓冲模式。禁用缓冲区,直接操作设备。 |
QIODevice::NewOnly | 0x0100 | 仅在文件不存在时创建文件。如果文件已存在,操作将失败。 |
QIODevice::Existing | 0x0200 | 仅在文件已存在时打开文件。如果文件不存在,操作将失败。 |
QIODevice::UnrestrictedRead | 0x0400 | 允许未受限制的读取访问。可以用于某些情况下需要特别权限的读取操作。 |
3.对打开方式返回值判断
- 对open方式打开的文件都有一个布尔类型的返回值,成功为true,失败为false,可以借此判断是否以指定方式打开成功。
- 代码举例
bool ret = fn.open(QIODevice::ReadOnly);if(ret == false){ui->textEdit->setText("以只读方式打开失败");return;}
4. 文件的读和写
- 小知识
- char buf[2024] = {0}; 这段代码的作用是创建一个长度为 2024的字符数组,并将数组中的每个字符元素初始化为 0,也就是空字符 ‘\0’。在C/C++中,字符串是以空字符 ‘\0’ 结束的字符序列。这样的初始化确保了数组在使用前不会包含任何未定义的值,非常适合用来存储字符串或者二进制数据。
1.文件的读
- 指定一个char类型的数组用来存储读的数据。可以指定较大的数组来一次性读取完所有的数据。也可以创建文本流的方式从文件中读取数据(灵活)。
- 一次性
char buf[20400] ={0};r = fn.read(buf,sizeof(buf));if(r<0){ui->textEdit->setText("读取失败");return;}ui->textEdit->setText(buf);
- 一行一行读
//需要包含QTextStream头文件
QTextStream fntext(&fn);fn是QFile类型,指定了文件的读取路径ui->textEdit->clear();while(!fntext.atEnd()){//fntext.atEnd():检查文件是否已经读取到末尾。QString line =fntext.readLine();ui->textEdit->append(line);}
2. 文件的写
- 有重新写入和追加写入两种方式,一般用的比较多的是追加写入
- 追加写入
- 打开文件的方式是Append。文件写指针会自动定位到文件末尾,从而确保新写入的数据不会覆盖文件中已有的数据。
- 获取写入的文本QString txtStr = ui->textEdit->toPlainText();
- 将QString类型文本转换为std::string类型,也就是c++类型,因此可以使用C++标准库的字符串操作std::string str = txtStr.toStdString();
- 因为write的参数是指针,长度。所以用c_str();获取c风格字符串指针,是常量指针喔。*const char pchar = str.c_str();
- 为了保证QString 在转换为本地8位编码后正确地写入文件,处理可能存在的多字节字符。简单的说是因为文字的编码格式不一样,有utf-8,Gbk这种编码。采用toLocal8bit().length()能够获得一致的长度,从而避免字符截断或编码错误txtStr.toLocal8Bit().length()
- write写入,fn.write(pchar,txtStr.toLocal8Bit().length());,它也有返回值。返回小于0的数表示写入失败。
void Widget::btnAppendClickedSlotFun()
{int r;QFile fn(ui->lineEdit->text());bool ret = fn.open(QIODevice::Append);if(ret == false){ui->textEdit->setText("追加写入失败");return;}QString txtStr = ui->textEdit->toPlainText();std::string str = txtStr.toStdString();const char *pchar = str.c_str();r = fn.write(pchar,txtStr.toLocal8Bit().length());if(r<0){ui->textEdit->setText("写入失败");return;}fn.close();
}
- 重新写入
- 它和追加写入的方式只有打开文件的方式的不一样,也就导致文件写指针的位置不一样。
- fn.open(QIODevice::WriteOnly|QIODevice::Truncate);//writeonly保证了文件以写的方式打开,truncate保证了文件当中有内容也被清空。
void Widget::btnWriteClickedSlotFun()
{int r;QFile fn(ui->lineEdit->text());bool ret = fn.open(QIODevice::WriteOnly|QIODevice::Truncate);if(ret==false){ui->textEdit->setText("打开写入失败");return;}QString txtStr = ui->textEdit->toPlainText();std::string stdstr = txtStr.toStdString();const char *pchar = stdstr.c_str();r = fn.write(pchar,txtStr.toLocal8Bit().length());if(r<0){ui->textEdit->setText("写入失败");return;}fn.close();
}
- 注意点
- 当我们将文件给读取出来,并在文件内容上修改,一般采用重新写入。追加写入可以加日志之类的。
4. 文件的创建、关闭和删除
- 文件的创建,给fn一个不存在的文件路径名即可
void Widget::btnCreateClickedSlotFun()
{QFile fn(ui->lineEdit->text());fn.open(QIODevice::WriteOnly);//避免空文件打开时警告fn.close();
}
- 文件的关闭使用close函数即可。**fn.close();**读写完毕之后都要关闭
- 文件的删除使用remove函数即可。fn.remove();
5.整体代码
//widget.h
#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACEclass Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();
public slots:void btnOpenClickedSlotFun();void btnReadClickedSlotFun();void btnWriteClickedSlotFun();void btnAppendClickedSlotFun();void btnDeleteClickedSlotFun();void btnCreateClickedSlotFun();private:Ui::Widget *ui;
};
#endif // WIDGET_H//widget.h
#include "widget.h"
#include "ui_widget.h"
#include<QTextStream>
#include<QFileDialog>
Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);ui->lineEdit->setText("打开文件存放的路径");ui->btnOpen->setText("打开文件");connect(ui->btnOpen,SIGNAL(clicked()),this,SLOT(btnOpenClickedSlotFun()));ui->btnRead->setText("读取文件");connect(ui->btnRead,SIGNAL(clicked()),this,SLOT(btnReadClickedSlotFun()));ui->btnWrite->setText("写入文件");connect(ui->btnWrite,SIGNAL(clicked()),this,SLOT(btnWriteClickedSlotFun()));ui->btnAppend->setText("追加写入文件");connect(ui->btnAppend,SIGNAL(clicked()),this,SLOT(btnAppendClickedSlotFun()));ui->btnDelete->setText("删除文件");connect(ui->btnDelete,SIGNAL(clicked()),this,SLOT(btnDeleteClickedSlotFun()));ui->btnCreate->setText("创建文件");connect(ui->btnCreate,SIGNAL(clicked()),this,SLOT(btnCreateClickedSlotFun()));}Widget::~Widget()
{delete ui;
}void Widget::btnOpenClickedSlotFun()
{QString fn = QFileDialog::getOpenFileName(this,"openFile","/mnt/hgfs/linux_learn/QT_teacher_information/");if(fn.isEmpty()){ui->lineEdit->setText("选中目录失败,请重新选中");return ;}ui->lineEdit->setText(fn);
}void Widget::btnReadClickedSlotFun()
{int r;QFile fn(ui->lineEdit->text());bool ret = fn.open(QIODevice::ReadOnly);if(ret == false){ui->textEdit->setText("打开失败");return;}/* char buf[20400] ={0};r = fn.read(buf,sizeof(buf));if(r<0){ui->textEdit->setText("读取失败");return;}ui->textEdit->setText(buf);*/QTextStream fntext(&fn);ui->textEdit->clear();while(!fntext.atEnd()){QString line =fntext.readLine();ui->textEdit->append(line);}fn.close();
}void Widget::btnWriteClickedSlotFun()
{int r;QFile fn(ui->lineEdit->text());bool ret = fn.open(QIODevice::WriteOnly|QIODevice::Truncate);if(ret==false){ui->textEdit->setText("打开写入失败");return;}QString txtStr = ui->textEdit->toPlainText();std::string stdstr = txtStr.toStdString();const char *pchar = stdstr.c_str();r = fn.write(pchar,txtStr.toLocal8Bit().length());if(r<0){ui->textEdit->setText("写入失败");return;}fn.close();
}void Widget::btnAppendClickedSlotFun()
{int r;QFile fn(ui->lineEdit->text());bool ret = fn.open(QIODevice::Append);if(ret == false){ui->textEdit->setText("追加写入失败");return;}QString txtStr = ui->textEdit->toPlainText();std::string str = txtStr.toStdString();const char *pchar = str.c_str();r = fn.write(pchar,txtStr.toLocal8Bit().length());if(r<0){ui->textEdit->setText("写入失败");return;}fn.close();
}void Widget::btnDeleteClickedSlotFun()
{QFile fn(ui->lineEdit->text());bool r = fn.remove();if(r==false){ui->textEdit->setText("删除失败");return;}else{ui->textEdit->setText("删除成功");}}void Widget::btnCreateClickedSlotFun()
{QFile fn(ui->lineEdit->text());fn.open(QIODevice::WriteOnly);//避免空文件打开时警告fn.close();
}
- 布局