public
:
QGridLayout *layout=
new
QGridLayout
(
this
);
QPushButton *b1=
new
QPushButton
(
this
);
QPushButton *b2=
new
QPushButton
(
this
);
QTextEdit *editor=
new
QTextEdit
(
this
);
#
endif
#include "Widget.h"
#include <QGridLayout>
#include <QPushButton>
#include <QTextEdit>
#include <QFile>
#include <QFileDialog>
Widget::Widget(QWidget *parent)
: QWidget(parent)
b1->setText("读取文本");
b2->setText("写入文本");
layout->addWidget(b1,0,0,1,1);
layout->addWidget(b2,0,1,1,1);
layout->addWidget(editor,1,0,1,2);
this->setLayout(layout);
this->resize(300,400);
connect(b1,&QPushButton::clicked,this,&Widget::openFile);
Widget::~Widget()
void Widget::openFile(){
QString path=QFileDialog::getOpenFileName(this,"open","C:/Users/MSI-NB/Desktop","text(*.txt)");
if(!path.isEmpty()){
QFile file(path);
file.open(QIODevice::ReadOnly);
QByteArray array=file.readAll();
this->editor->setText(array);
file.close();
实现效果:
如果不想一次性读入所有文本,而是想要逐行读取,可以这样来实现:
#include "Widget.h"
#include <QGridLayout>
#include <QPushButton>
#include <QTextEdit>
#include <QFile>
#include <QFileDialog>
Widget::Widget(QWidget *parent)
: QWidget(parent)
b1->setText("读取文本");
b2->setText("写入文本");
layout->addWidget(b1,0,0,1,1);
layout->addWidget(b2,0,1,1,1);
layout->addWidget(editor,1,0,1,2);
this->setLayout(layout);
this->resize(300,400);
connect(b1,&QPushButton::clicked,this,&Widget::openFile);
Widget::~Widget()
void Widget::openFile(){
QString path=QFileDialog::getOpenFileName(this,"open","C:/Users/MSI-NB/Desktop","text(*.txt)");
if(!path.isEmpty()){
QFile file(path);
file.open(QIODevice::ReadOnly);
QByteArray array;
while(!file.atEnd()){
array+=file.readLine();
this->editor->setText(array);
file.close();
实现效果是一模一样的:
(只是在趁机安利Jay的乱舞春秋(◔v◔)
回想在我们的日常操作中,写文件的步骤也是先对文本进行编辑,接着打开一个文件对话框,再选择要保存的路径,其实与读文件的实现方法差不多:
#ifndef WIDGET_H
#define WIDGET_H
#pragma execution_character_set("utf-8")
#include <QWidget>
#include <QGridLayout>
#include <QPushButton>
#include <QTextEdit>
class Widget : public QWidget
Q_OBJECT
public:
Widget(QWidget *parent = 0);
~Widget();
protected:
void Widget::openFile();
void Widget::saveFile();
public:
QGridLayout *layout=new QGridLayout(this);
QPushButton *b1=new QPushButton(this);
QPushButton *b2=new QPushButton(this);
QTextEdit *editor=new QTextEdit(this);
#endif
#include "Widget.h"
#include <QGridLayout>
#include <QPushButton>
#include <QTextEdit>
#include <QFile>
#include <QFileDialog>
Widget::Widget(QWidget *parent)
: QWidget(parent)
b1->setText("读取文本");
b2->setText("写入文本");
layout->addWidget(b1,0,0,1,1);
layout->addWidget(b2,0,1,1,1);
layout->addWidget(editor,1,0,1,2);
this->setLayout(layout);
this->resize(300,400);
connect(b1,&QPushButton::clicked,this,&Widget::openFile);
connect(b2,&QPushButton::clicked,this,&Widget::saveFile);
Widget::~Widget()
void Widget::openFile(){
QString path=QFileDialog::getOpenFileName(this,"open","C:/Users/MSI-NB/Desktop","text(*.txt)");
if(!path.isEmpty()){
QFile file(path);
file.open(QIODevice::ReadOnly);
QByteArray array=file.readAll();
this->editor->setText(array);
file.close();
void Widget::saveFile(){
QString text=this->editor->toPlainText();
QString path=QFileDialog::getSaveFileName(this,"save","C:/Users/MSI-NB/Desktop","text(*.txt)");
QFile file;
file.setFileName(path);
file.open(QIODevice::WriteOnly);
file.write(text.toUtf8());
file.close();
实现效果:
首先,我打开原来的歌词文件,在文本编辑区域修改了一句歌词,接着点击“写入文本”按钮,指定文件保存的路径(这里我没有新建一个文件,而是直接覆盖了原来的文件),然后再点击“读取文本”,读取出刚刚保存的文件,发现歌词已经被成功修改了。
在读取文本框内容的时候,我们调用了toPlainText()
方法将文本转化为QString类型的字符串,但是要调用write()
方法往文件中写入时,需要以QByteArray字节数组的形式,因此还需要调用toUtf8()
方法将QString类型的字符串进行转化。
在这里补充几个Qt中常用的不同类型的文本流之间转化的方法:
QString → QByteArray:
QByteArray array=str.toUft8();
QString对象不仅可以转化为UTF-8编码的字节数组,还可以转化为其它方式编码的字节数组,比如使用本地平台编码方式:
QByteString array=str.toLocal8Bit();
QString → std::string(C++标准字符串) → char *:
qDebug()<<"typing "<<str.toStdString().data();
QByteArray → char *:
char *b=array.data();
char * → QString:
char *p="abc";
QString str=QString(p);
#include "Widget.h"
#include <QGridLayout>
#include <QPushButton>
#include <QTextEdit>
#include <QFile>
#include <QFileDialog>
#include <QDebug>
Widget::Widget(QWidget *parent)
: QWidget(parent)
b1->setText("读取文本");
b2->setText("写入文本");
layout->addWidget(b1,0,0,1,1);
layout->addWidget(b2,0,1,1,1);
layout->addWidget(editor,1,0,1,2);
this->setLayout(layout);
this->resize(300,400);
connect(b1,&QPushButton::clicked,this,&Widget::openFile);
connect(b2,&QPushButton::clicked,this,&Widget::saveFile);
Widget::~Widget()
void Widget::openFile(){
QString path=QFileDialog::getOpenFileName(this,"open","C:/Users/MSI-NB/Desktop","text(*.txt)");
if(!path.isEmpty()){
QFile file(path);
file.open(QIODevice::ReadOnly);
QByteArray array=file.readAll();
this->editor->setText(array);
file.close();
void Widget::saveFile(){
QString text=this->editor->toPlainText();
QString path=QFileDialog::getSaveFileName(this,"save","C:/Users/MSI-NB/Desktop","text(*.txt)");
QFile file;
file.setFileName(path);
file.open(QIODevice::WriteOnly);
file.write(text.toUtf8());
QByteArray qba=text.toUtf8();
char *b=qba.data();
qDebug()<<"typing "<<qba;
qDebug()<<"typing "<<b;
file.close();
实现效果:
输入英文,调用toUtf8()后得到的QByteArray对象与调用toUtf8().data()后得到的char * 变量的区别在于,前者多了双引号。
输入中文,调用toUtf8()后得到的QByteArray对象与调用toUtf8().data()后得到的char * 变量的区别除了前者多了双引号之外,输出char * 变量可以得到完整的中文字符串将字符串,而输出QByteArray对象得到的是一些UTF-8表示形式。
注意:如果需要输出中文,应该先用toUtf8()
方法转化成Unicode编码,再用data()
方法转化成我们可以识别的中文字符串。
QFileInfo获取文件信息
文件自身携带一些信息,如文件大小、创建时间、后缀名等等,要获取这些信息,需要用到QFileInfo。使用QFileInfo需要先引入<QFileInfo>
头文件。
让我们在刚才读写文件的例子中,获取一下文件的信息:
#include "Widget.h"
#include <QGridLayout>
#include <QPushButton>
#include <QTextEdit>
#include <QFile>
#include <QFileDialog>
#include <QDebug>
#include <QFileInfo>
#include <QDateTime>
Widget::Widget(QWidget *parent)
: QWidget(parent)
b1->setText("读取文本");
b2->setText("写入文本");
layout->addWidget(b1,0,0,1,1);
layout->addWidget(b2,0,1,1,1);
layout->addWidget(editor,1,0,1,2);
this->setLayout(layout);
this->resize(300,400);
connect(b1,&QPushButton::clicked,this,&Widget::openFile);
connect(b2,&QPushButton::clicked,this,&Widget::saveFile);
Widget::~Widget()
void Widget::openFile(){
QString path=QFileDialog::getOpenFileName(this,"open","C:/Users/MSI-NB/Desktop","text(*.txt)");
if(!path.isEmpty()){
QFile file(path);
file.open(QIODevice::ReadOnly);
QByteArray array=file.readAll();
this->editor->setText(array);
QFileInfo info(path);
qDebug()<<"文件名:"<<info.fileName();
qDebug()<<"文件大小:"<<info.size();
qDebug()<<"文件类型:"<<info.suffix();
qDebug()<<"文件创建时间:"<<info.created().toString("yyyy-MM-dd hh:mm:ss");
file.close();
实现效果:
说明:文件大小以字节(Byte)为单位。
created()
方法返回一个QDateTime对象,要想以文本形式输出时间,还需要调用toString()
方法,并且指定输出的格式。调用toString()方法需要先引入<QDateTime>
头文件,下面是帮助文档中对于格式的详细描述:
QDataStream读写文件
如果我们想以二进制流的形式对文件进行读写操作,就需要用到QDataStream。使用QDataStream,不仅可以操作文本文件,还可以操作音频、视频等类型的文件。
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#pragma execution_character_set("utf-8")
class Widget : public QWidget
Q_OBJECT
public:
Widget(QWidget *parent = 0);
~Widget();
void Widget::writeStream();
void Widget::readStream();
#endif
#include "Widget.h"
#include <QFile>
#include <QDataStream>
#include <QDebug>
Widget::Widget(QWidget *parent)
: QWidget(parent)
writeStream();
readStream();
Widget::~Widget()
void Widget::writeStream(){
QFile file("C:/Users/MSI-NB/Desktop/datastream.txt");
file.open(QIODevice::WriteOnly);
QDataStream stream(&file);
stream<<QString("黑色柳丁")<<3155530;
file.close();
实现效果:
这个文件就算能直接打开也没有什么意义,因为它的内容是二进制流,所以我们打开看到的是一些乱码,需要通过QDataStream把它读出来,并转换成我们想要的格式。
#include "Widget.h"
#include <QFile>
#include <QDataStream>
#include <QDebug>
Widget::Widget(QWidget *parent)
: QWidget(parent)
writeStream();
readStream();
Widget::~Widget()
void Widget::writeStream(){
QFile file("C:/Users/MSI-NB/Desktop/datastream.txt");
file.open(QIODevice::WriteOnly);
QDataStream stream(&file);
stream<<QString("黑色柳丁")<<3155530;
file.close();
void Widget::readStream(){
QFile file("C:/Users/MSI-NB/Desktop/datastream.txt");
file.open(QIODevice::ReadOnly);
QDataStream stream(&file);
QString str;
int num;
stream>>str>>num;
qDebug()<<str.toUtf8().data()<<num;
注意:从QDataStream对象中输出的数据会根据类型自动匹配,且读取和写入的顺序是一样的,先写入的会先被读取。
实现效果:
Tips:
调试的过程中,经常使用到qDebug(),但是还要打一对括号很麻烦,我们可以定义一个宏,用c++中的输出cout来替代。另外,利用c中的__FILE__
和__LINE__
,可以指示当前语句所在的源文件的文件名
和在文件中的位置
(行数)。(__FILE__和__LINE__都是大小写敏感)
#include "Widget.h"
#include <QFile>
#include <QDataStream>
#include <QDebug>
#define cout qDebug()<<"["<<__FILE__<<":"<<__LINE__<<"]"
Widget::Widget(QWidget *parent)
: QWidget(parent)
writeStream();
readStream();
Widget::~Widget()
void Widget::writeStream(){
QFile file("C:/Users/MSI-NB/Desktop/datastream.txt");
file.open(QIODevice::WriteOnly);
QDataStream stream(&file);
stream<<QString("黑色柳丁")<<3155530;
file.close();
void Widget::readStream(){
QFile file("C:/Users/MSI-NB/Desktop/datastream.txt");
file.open(QIODevice::ReadOnly);
QDataStream stream(&file);
QString str;
int num;
stream>>str>>num;
qDebug()<<str.toUtf8().data()<<num;
cout<<str<<num;
实现效果:
要想通过文本的方式操作文件,并为其指定读写的编码,就需要用到QTextStream。QTextStream的用法与QDataStream基本一致。主要的区别是QTextStream对象可以调用setCodec()方法来指定编码方式,参数如下:
但是用这个方式读文件会出现我们不想要的结果,因为它将所有内容都当成是字符串,这样一来,原先跟在QString字符串后面的int型数据也被识别成字符串,所以最好还是用readAll()
或者readLine()
来读取文件。
QBuffer用来操作内存文件。它的用法与QFile差不多,也需要先创建内存文件对象,打开内存文件,写入或读取内存文件,最后关闭内存文件。调用write()方法往内存文件中写入的内存其实是写在缓冲区的,要从缓冲区里把数据取出来,需要调用QBuffer对象的buffer()方法。另外,放到缓冲区的内容会根据写入的顺序依次排列,取出时也是取出缓冲区中所有的内容。
#include "Widget.h"
#include <QBuffer>
#include <QDebug>
Widget::Widget(QWidget *parent)
: QWidget(parent)
writeFile();
Widget::~Widget()
void Widget::writeFile(){
QBuffer memFile;
memFile.open(QIODevice::WriteOnly);
memFile.write("hello");
memFile.write("hi");
memFile.close();
qDebug()<<memFile.buffer();
实现效果:
在创建QBuffer对象时,可以在构造函数的参数列表中传入一个QByteArray对象,为这个QBuffer对象指定一个缓冲区。那么,在对QBuffer对象调用write()进行写入时,就会将数据写入到QByteArray对象中。
#include "Widget.h"
#include <QBuffer>
#include <QDebug>
Widget::Widget(QWidget *parent)
: QWidget(parent)
writeFile();
Widget::~Widget()
void Widget::writeFile(){
QByteArray array;
QBuffer memFile(&array);
memFile.open(QIODevice::WriteOnly);
memFile.write("i am writing ");
memFile.write("in buffer");
memFile.close();
qDebug()<<"array is "<<array;
实现效果:
P.S:如有错误,欢迎指正~