目录
1、QT中的IO操作
QT中IO操作的处理方式
-Qt通过统一的接口简化了文件与外部设备的操作方式
-Qt中的文件被看作一种特殊的外部设备 ,Qt中的文件操作与外部设备的操作相同
IO操作中的关键函数接口
-打开设备: bool open(OpenMode mode)
-读取数据:QByteArray read(qint64 maxSize)
-写入数据:qint64 write(const QByteArray& byteArray)
-关闭设备: void close()
IO操作的本质:连续存储空间的数据读写 (内存,硬盘、串口、USB口等)
Qt中IO设备的类型
-顺序存取设备 :只能从头开始顺序的读写数据,不能指定数据的读写位置
-随机存取设备 :可以定位到任意的位置进行数据的读写(seek function)
Qt中IO设备的继承层次图
2、QFile、QFileInfo
QFile是Qt中用于文件操作的类 ,QFile对象对应到计算机上的一个文件
QFilelnfo类用于读取文件属性信息
#include <QtCore/QCoreApplication>
#include <QFile>
#include <QByteArray>
#include <QFileInfo>
#include <QDateTime>
#include <QDebug>
void write(QString f)
{
QFile file(f);
if(file.open(QIODevice::WriteOnly | QIODevice::Text))
{
file.write("QQ: 111\n");
file.write("From: 222 \n");
file.close();
}
}
void read(QString f)
{
QFile file(f);
if(file.open(QIODevice::ReadOnly | QIODevice::Text))
{
QByteArray ba = file.readAll();
QString s(ba);
qDebug() << s;
}
}
void info(QString f)
{
QFile file(f);
QFileInfo info(file);
qDebug() << info.exists();
qDebug() << info.isFile();
qDebug() << info.isReadable();
qDebug() << info.isWritable();
qDebug() << info.created();//使用QDateTime头文件
qDebug() << info.lastRead();
qDebug() << info.lastModified();
qDebug() << info.path();
qDebug() << info.fileName();
qDebug() << info.suffix();
qDebug() << info.size();
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
//write("C:\\Users\\wss\\Desktop\\test.text");
//write("C:/Users/wss/Desktop/test.text");
//read("C:/Users/wss/Desktop/test.text");
info("C:/Users/wss/Desktop/test.text");
return a.exec();
}
2、QTemporaryFile
Qt中提供了临时文件操作类QTemporaryFile
-安全地创建一个全局唯一的临时文件 ,当对象销毁时对应的临时文件将被删除
-临时文件的打开方式为QIODevice::ReadWrite (默认)
-临时文件常用于大数据传递或者进程间通信的场合
#include <QtCore/QCoreApplication>
#include <QTemporaryFile>
#include <QFileInfo>
#include <QDebug>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QTemporaryFile tempFile;
if( tempFile.open() )
{
tempFile.write("This is a temporary file\n");
tempFile.close();
}
QFileInfo info(tempFile);
qDebug() << info.isFile();
qDebug() << info.path();
qDebug() << info.fileName();
return a.exec();
}
3、QTextStream 与 QDataStream
Qt中将文件类型分为2大类
- 文本文件 :文件内容是可读的文本字符
- 数据文件 :文件内容是直接的二进制数据
QFile直接支持文本文件和数据文件的读写
- qint64 read(char* data, qint64 maxSize)
- QByteArray read(qint64 maxSize)
- qint64 write(const char* data, qint64 maxSize)
- qint64 write(const QByteArray& byteArray)
#include <QtCore/QCoreApplication>
#include <QFile>
#include <QDebug>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QFile file("C:/Users/wss/Desktop/test.hex");
if( file.open(QIODevice::WriteOnly) ) // 没有指明文本类型,默认以二进制方式打开
{
QString dt = "QIODevice";
double value = 3.14;
file.write(dt.toStdString().c_str());
file.write(reinterpret_cast<char*>(&value), sizeof(value));
file.close();
}
if( file.open(QIODevice::ReadOnly) )
{
QString dt = "";
double value = 0;
dt = QString(file.read(9)); // 返回QByteArray对象
file.read(reinterpret_cast<char*>(&value), sizeof(value));
file.close();
qDebug() << dt;
qDebug() << value;
}
return a.exec();
}
文本流和数据流
Qt提供辅助类简化了文本文件 / 数据文件的读写
- QTextStream :写入的数据全部转换为可读文本
- QDataStream :写入的数据根据类型转换为二进制数据
#include <QtCore/QCoreApplication>
#include <QFile>
#include <QTextStream>
#include <QDataStream>
#include <QDebug>
void text_stream_test(QString f)
{
QFile file(f); // 创建IO设备对象
if( file.open(QIODevice::WriteOnly | QIODevice::Text) ) // 文本,只写方式打开文件
{
QTextStream out(&file); // 初始化文本流
out << QString("QIODevice") << endl;
out << QString("Result: ") << endl;
out << 5 << '*' << 6 << '=' << 5 * 6 << endl;
file.close();
}
if( file.open(QIODevice::ReadOnly | QIODevice::Text) )
{
QTextStream in(&file);
while( !in.atEnd() )
{
QString line = in.readLine();
qDebug() << line;
}
file.close();
}
}
void data_stream_test(QString f)
{
QFile file(f);
if( file.open(QIODevice::WriteOnly) )
{
QDataStream out(&file); // 初始化数据流
out.setVersion(QDataStream::Qt_4_7);
out << QString("QIODevice");
out << QString("Result: ");
out << 3.14;
file.close();
}
if( file.open(QIODevice::ReadOnly) )
{
QDataStream in(&file);
QString dt = "";
QString result = "";
double value = 0;
in.setVersion(QDataStream::Qt_4_7);
in >> dt;
in >> result;
in >> value;
file.close();
qDebug() << dt;
qDebug() << result;
qDebug() << value;
}
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
text_stream_test("C:/Users/wss/Desktop/text.txt");
data_stream_test("C:/Users/wss/Desktop/data.dat");
return a.exec();
}
不同Qt版本的数据流文件格式可能不同
- void setVersion(int v) // 设置读写版本号
- int version() const // 获取读写版本号
当数据流文件可能在不同版本的Qt程序间传递数据时,需要考虑版本问题!
下面写了一个大致修复后缀名的代码,用到了数据流
由于word文档本质就是压缩为文档,所以会被解析为zip
void UpdateThread::fixFileSuffix(QString path)
{
QDir dir(path);
if(path == "" || !dir.exists())
return;
QFileInfoList subFileList = dir.entryInfoList(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot | QDir::CaseSensitive);
if(subFileList.empty())
return;
for (int i = 0; !m_stop && (i < subFileList.size()); i++)
{
if(subFileList[i].isDir())
{
fixFileSuffix(subFileList[i].absoluteFilePath());
}
else
{
QFile file(subFileList[i].absoluteFilePath());
QString oldSuffix = subFileList[i].suffix();
char buffer[8];
memset(buffer, 0, sizeof (buffer));
if(file.open(QIODevice::ReadOnly))
{
QDataStream in(&file);
in.readRawData(buffer, sizeof(buffer));
QByteArray ba(buffer, sizeof(buffer));
//qDebug() << "ba : " << ba << endl;
QByteArray two = ba.mid(0, 2).toHex().toUpper();
QByteArray three = ba.mid(0, 3).toHex().toUpper();
QByteArray four = ba.mid(0, 4).toHex().toUpper();
QByteArray five = ba.mid(0, 5).toHex().toUpper();
QByteArray lastFour = ba.mid(4, 4).toHex().toUpper();
QByteArray seven = ba.mid(0, 7).toHex().toUpper();
QByteArray eight = ba.toHex().toUpper();
QString curDir = subFileList[i].absolutePath();
QString baseName = subFileList[i].baseName();
QString suffix = "";
if(two == QByteArray("FFD8"))
suffix = ".jpg";
else if(three == QByteArray("494433") || three == QByteArray("FFFB50"))
suffix = ".mp3"; // 这些文件标识都是随便搜的,很多肯定有版本差异
else if(three == QByteArray("89504E") || four == QByteArray("89504E47"))
suffix = ".png";
else if(four == QByteArray("47494638"))
suffix = ".gif";
else if(four == QByteArray("D0CF11E0") || four == QByteArray("0D444F43") ||
eight == QByteArray("31BE000000AB0000") || four == QByteArray("7FFE340A"))
suffix = ".doc";
else if(four == QByteArray("504B0304") && (oldSuffix != "docx" && oldSuffix != "doc"))
suffix = ".zip";
else if(four == QByteArray("52617221"))
suffix = ".rar";
else if(four == QByteArray("57415645") || four == QByteArray("52494646"))
suffix = ".wav";
else if(four == QByteArray("41564920"))
suffix = ".avi";
else if(four == QByteArray("2E524D46 "))
suffix = ".rm";
else if(four == QByteArray("000001BA") || four == QByteArray("000001B3") )
suffix = ".mpg";
else if(four == QByteArray("6D6F6F76") || four == QByteArray("6D646174"))
suffix = ".mov";
else if(lastFour == QByteArray("66747970"))
suffix = ".mp4";
else if(seven == QByteArray("255044462D312E") || four == QByteArray("25504446")
|| three == QByteArray("255044"))
suffix = ".pdf";
else if(two == QByteArray("FEFF") || two == QByteArray("FFFE") || three == QByteArray("EFBBBF"))
suffix = ".txt";
else if(five == QByteArray("68746D6C3E"))
suffix = ".html";
else if(five == QByteArray("3C3F786D6C"))
suffix = ".xml";
else if(five == QByteArray("7B5C727466"))
suffix = ".rtf";
else if(five == QByteArray("377ABCAF271C"))
suffix = ".7z";
else if(four == QByteArray("464C5601"))
suffix = ".flv";
else if(two == QByteArray("4D5A") && (oldSuffix != "dll" && oldSuffix != "com"))
suffix = ".exe";
else if(three == QByteArray("00FFFF"))
suffix = ".img";
else if(eight == QByteArray("64383A616E6E6F75"))
suffix = ".torrent";
else
suffix = "";
if(suffix != "" && !m_stop)
file.rename(curDir + "/" + baseName + suffix);
file.close();
}
}
if(!m_stop)
emit updateUI(1);
}
}
4、QBuffer
Qt中缓冲区的概念
-缓冲区的本质为一段连续的存储空间 ,QBuffer是Qt中缓冲区相关的类
-在Qt中可以将缓冲区看作一种特殊的IO设备 ,文件流辅助类可以直接用于操作缓冲区
QBuffe缓冲区的使用场合
-在线程间进行不同类型的数据传递
-缓存外部设备中的数据返回
-数据读取速度小于数据写入速度
#include <QtCore/QCoreApplication>
#include <QBuffer>
#include <QByteArray>
#include <QDataStream>
#include <QDebug>
void write_buffer(int type, QBuffer& buffer)
{
if( buffer.open(QIODevice::WriteOnly) )
{
QDataStream out(&buffer);
out << type;
if( type == 0 )
{
out << QString("PI");
out << QString("3.1415");
}
else if( type == 1 )
{
out << 3;
out << 1415;
}
else if( type == 2 )
{
out << 3.1415;
}
buffer.close(); //关闭IO设备
}
}
void read_buffer(QBuffer& buffer)
{
if( buffer.open(QIODevice::ReadOnly) )
{
int type = -1;
QDataStream in(&buffer);
in >> type;
if( type == 0 )
{
QString dt = "";
QString pi = "";
in >> dt;
in >> pi;
qDebug() << dt;
qDebug() << pi;
}
else if( type == 1 )
{
int a = 0;
int b = 0;
in >> a;
in >> b;
qDebug() << a;
qDebug() << b;
}
else if( type == 2 )
{
double pi = 0;
in >> pi;
qDebug() << pi;
}
buffer.close();
}
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QByteArray array;
QBuffer buffer(&array); // 缓冲区对象关联到内存
write_buffer(2, buffer); // 写缓冲区
read_buffer(buffer);
return a.exec();
}
5、QDir
QDir是Qt中功能强大的目录操作类
-Qt中的目录分隔符统一使用 '/'
-QDir能够对目录进行任意操作(创建,删除,重命名)
-QDir能够获取指定目录中的所有条目(文件和文件夹) ,QDir能够使用过滤字符串获取指定条目
-QDir能够获取系统中的所有根目录
#include <QtCore/QCoreApplication>
#include <QDir>
#include <QFileInfo>
#include <QFileInfoList>
#include <QDebug>
void test_dir()
{
const char* PATH = "C:/Users/wss/Desktop/QDir";
QDir dir;
if( !dir.exists(PATH) )
{
dir.mkdir(PATH);
}
if( dir.exists(PATH) )
{
dir.cd(PATH);
QStringList list = dir.entryList();
for(int i=0; i<list.count(); i++)
{
qDebug() << list[i];
}
}
}
unsigned int calculate_size(QString path)
{
QFileInfo info(path);
unsigned int ret = 0;
if( info.isFile() )
{
ret = info.size();
}
else if( info.isDir() )
{
QDir dir(path);
QFileInfoList list = dir.entryInfoList();
for(int i=0; i<list.count(); i++)
{
if( (list[i].fileName() != ".") && (list[i].fileName() != "..") )
{
ret += calculate_size(list[i].absoluteFilePath());
}
}
}
return ret;
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
test_dir();
qDebug() << calculate_size("C:/Users/wss/Desktop/QDir");
return a.exec();
}
6、文件系统监视器
QFileSystemWatcher用于监控文件和目录的状态变化
-能够监控特定目录和文件的状态 ,能够同时对多个目录和文件进行监控
-当目录或者文件发生改变时将触发信号 ,可以通过信号与槽的机制捕捉信号并做出响应
Watcher.h
#ifndef _WATCHER_H_
#define _WATCHER_H_
#include <QObject>
#include <QFileSystemWatcher>
class Watcher : public QObject
{
Q_OBJECT
QFileSystemWatcher m_watcher;
private slots:
void statusChanged(const QString& path);//参数可以查阅Qt帮助
public:
explicit Watcher(QObject *parent = 0);
void addPath(QString path);
};
#endif // WATCHER_H
Watcher.cpp
#include "Watcher.h"
#include <QDebug>
Watcher::Watcher(QObject *parent) : QObject(parent)
{
connect(&m_watcher, SIGNAL(fileChanged(const QString&)), this, SLOT(statusChanged(const QString&)));
connect(&m_watcher, SIGNAL(directoryChanged(const QString&)), this, SLOT(statusChanged(const QString&)));
}
void Watcher::statusChanged(const QString &path)
{
qDebug() << path << "is changed!";
}
void Watcher::addPath(QString path)
{
m_watcher.addPath(path);
}
main.cpp
#include <QtCore/QCoreApplication>
#include "Watcher.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
Watcher watcher;
watcher.addPath("C:/Users/wss/Desktop/text.txt");
watcher.addPath("C:/Users/wss/Desktop/QDir");
return a.exec();
}