阅读量:0
文件操作和文件读写
- 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_NAMESPACE class Widget : public QWidget { Q_OBJECT public: 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(); }
- 布局