作为C++跨平台图形界面开发框架,Qt5不仅提供了强大的界面构建能力,在文件操作方面同样具备出色的功能支持。今天我们就来全面探索Qt5的文件操作能力,看看它如何让我们对文件系统为所欲为:创建新文件夹、读写文本内容、删改文件名,甚至操作INI和XML文件。跟着我一起,开启Qt5文件系统之旅!


一、创建文件夹:轻松建立自己的根据地


首先,我们从最基本的文件夹创建开始。在Qt5中,QDir类为我们提供了高效便捷的目录操作方法:

QString dirPath = QDir::currentPath() + "/MyFolder";

if(!QDir().exists(dirPath)){
    bool success = QDir().mkpath(dirPath);
    if(success){
        qDebug() << "Folder created successfully";
    } else {
        qDebug() << "Failed to create folder";
    }
}

我们首先通过QDir::currentPath()获取了当前执行程序的路径,并拼接上我们想要创建的文件夹名"MyFolder"。接下来通过QDir::exists判断该路径是否已存在,如果不存在就调用QDir::mkpath创建。

mkpath函数的好处是,如果待创建路径中的上层目录不存在,它会自动递归创建。比如这里的MyFolder目录即使在一个很深的路径下,Qt5也会顺利创建出来。操作的结果会通过返回值体现。

除此之外,QDir还提供了其他实用的目录操作函数,比如创建临时目录、遍历子目录列表、删除目录等,应有尽有,只等你掌握运用。


二、读写文件:单文件的读写小帮手


文件夹建好了,接下来就是对文件本身进行读写操作。Qt5通过QFile和QTextStream这两个类,让文件的读写变得无比轻松:

// 写入文件
QString filePath = dirPath + "/test.txt";
QFile file(filePath); 
if(file.open(QIODevice::WriteOnly | QIODevice::Text)){
    QTextStream out(&file);
    out << "Qt5 File Operations Demo\n";
    out << "Hello File Content!";
    file.close();
}

// 读取文件
if(file.open(QIODevice::ReadOnly | QIODevice::Text)){
    QTextStream in(&file); 
    QString content = in.readAll();
    qDebug() << content;
    file.close();
}

首先,我们指定了要操作的文件路径。然后通过open函数以不同的模式打开文件,QIODevice::WriteOnly用于写入,QIODevice::ReadOnly用于读取。

写入文件的时候,我们创建了QTextStream对象,通过它的<<操作符就能轻松将文本内容写入文件。读取文件时也是类似,通过QTextStream的readAll等函数获取内容。

最后,需要记得在操作完毕后close关闭文件。QFile和QTextStream会自动管理内存和编码,我们只需专注于文件内容的读写即可,高效简单。


三、修改文件内容:有了Qt5 文件纰漏了无


除了写入全新内容,有时我们还需要修改已有文件中的某些内容。不用担心,通过QFile的读写指针随机定位能力,Qt5就能满足你:

QFile file(filePath);
if(file.open(QIODevice::ReadWrite)){
    QTextStream stream(&file);
    QString content = stream.readAll();

    // 替换内容中的Hello为Howdy
    content.replace("Hello", "Howdy");

    // 移动指针到文件头
    stream.seek(0); 
    // 写入修改后的内容
    stream.operator<<(content);
    file.close();
}

首先我们以ReadWrite模式打开文件,并读取全部内容到QString中。然后使用QString的replace函数替换其中的"Hello"为"Howdy"。

修改内容后,我们将QTextStream的指针移动回文件头部,然后通过<<操作符将修改后的内容重新写入文件,原内容就被我们改写了。

这里的关键就在于QFile和QTextStream都能让我们随机移动指针的位置,实现任意读写。搭配QByteArray我们还能进行二进制内容的处理。Qt5赋予了我们无限的文件修改能力!


四、删除和重命名:轻松一挥手


文件的删除和重命名操作对于很多场景也是必不可少的。幸运的是,Qt5为此准备了简单的单行代码:

// 删除文件
bool removeSuccess = QFile::remove(filePath);

// 重命名文件
QString newName = "newtest.txt";
bool renameSuccess = QFile::rename(filePath, newName);

QFile::remove静态函数就能轻松删除指定文件,而QFile::rename则可以重命名文件。它们的返回值为bool类型,我们可以直接检查操作是否成功。

看见没有,Qt5就是这么体贴入微。无需冗长代码,就帮你解决了文件操作的大小事。而且,QFile在处理路径时也做了跨平台的处理,你完全不用担心不同操作系统间的路径差异。


五、INI文件读写: 持久化存储信息的宝典


有了对基础文件操作的认识,我们再来看看Qt5对INI文件的支持。INI文件经常被用于存储应用程序的各种配置选项、用户数据等。通过Qt5的QSettings,我们可以高效地读写INI文件:

# settings.ini
[General]
theme=dark
geometry=@Rect(100 100 500 400)

[RecentFiles]
file1=/home/user/file1.txt
file2=/home/user/file2.txt
file3=/home/user/file3.txt
size=3
// 写入 INI 配置
QSettings settings("settings.ini", QSettings::IniFormat);
settings.beginGroup("General");
settings.setValue("theme", "light");
settings.setValue("geometry", QRect(200, 200, 800, 600));
settings.endGroup();

// 读取 INI 配置
QSettings settings("settings.ini", QSettings::IniFormat);
settings.beginGroup("General"); 
QString theme = settings.value("theme", "dark").toString();
QRect geometry = settings.value("geometry").toRect();

settings.beginGroup("RecentFiles");
int size = settings.value("size", 0).toInt();
for(int i=0; i<size; ++i){
    QString key = QString("file%1").arg(i+1);
    QString filePath = settings.value(key).toString();
    qDebug() << filePath;
}

上面的示例代码中,我们首先创建了QSettings对象,并指定了INI文件的路径和格式(QSettings::IniFormat)。

写入INI文件时,我们使用beginGroup函数切换到General组,然后通过setValue函数设置theme和geometry这两个键值对。注意这里geometry的值是用QRect对象表示的。

读取INI文件时,我们同样先切换到General组,然后使用value函数获取theme和geometry键对应的值。如果键不存在,value函数会返回我们传入的默认值。

接下来我们切换到RecentFiles组,先获取size键的值表示最近文件的数量,然后遍历每个file键获取文件路径。这里我们使用了QString::arg便捷地构造了file1、file2这样的键名。

通过QSettings,我们不但可以方便地存取INI文件中的数据,还能自动处理不同数据类型之间的转换,非常强大。Qt5内置的INI文件访问功能,为我们优雅地解决了配置文件的持久化存储问题。


六、XML文件读写: 结构化数据的终极解决方案


相比INI文件的简单键值对结构,XML则拥有更加自由、更加规范的树状结构。Qt5为我们提供了QXmlStreamReader和QXmlStreamWriter两个类,用于高效地读写XML文件。让我们看看它们的魔力:

<!-- data.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<data>
  <owner>
    <name>Qt5</name>
    <organization>QtProject</organization>
  </owner>
  <items>
    <item>
      <name>Item 1</name>
      <value>21</value>
    </item>
    <item>
      <name>Item 2</name>
      <value>37</value>
    </item>
  </items>
</data>

// 写入XML文件
QFile file("data.xml");
file.open(QIODevice::WriteOnly);
QXmlStreamWriter xmlWriter(&file);
xmlWriter.setAutoFormatting(true);
xmlWriter.writeStartDocument();
xmlWriter.writeStartElement("data");

xmlWriter.writeStartElement("owner");
xmlWriter.writeTextElement("name", "Qt5");
xmlWriter.writeTextElement("organization", "QtProject"); 
xmlWriter.writeEndElement(); //owner

xmlWriter.writeStartElement("items");
xmlWriter.writeStartElement("item");
xmlWriter.writeTextElement("name", "Item 1");
xmlWriter.writeTextElement("value", "21");
xmlWriter.writeEndElement(); //item
... // 写入其他item
xmlWriter.writeEndElement(); //items

xmlWriter.writeEndElement(); //data
xmlWriter.writeEndDocument();
file.close();

// 读取XML文件 
QFile file("data.xml");
file.open(QIODevice::ReadOnly);
QXmlStreamReader xmlReader(&file);
while(!xmlReader.atEnd()){
    if(xmlReader.tokenType() == QXmlStreamReader::StartElement){
        if(xmlReader.name() == "item"){
            xmlReader.readNext();
            QString name = xmlReader.readElementText();
            xmlReader.readNext(); 
            QString value = xmlReader.readElementText();
            qDebug() << name << value;
        }
    }
    xmlReader.readNext();
}
file.close();

对于写入XML,我们首先创建了QXmlStreamWriter对象。通过一系列writeStartElement、writeTextElement和writeEndElement函数,我们就能轻松构建出规范的XML树形结构。

读取XML时,我们创建QXmlStreamReader对象,然后通过readNext不断前进XML文档的节点,并根据tokenType判断当前是开始元素、结束元素还是文本元素等。

这个示例中,我们检查到item开始元素后,读取了其中name和value元素的文本值并输出。通过QXmlStreamReader提供的多种API,我们就能高效地解析任何结构的XML数据。

XML无疑是表示结构化数据的不二之选。配合Qt5的完美支持,我们就能将数据变成XML备份、在程序间传递XML数据,或者与Web服务交换XML报文等等,畅通无阻。


编码之外 你还可以…


本文我们系统地学习了Qt5对文件和数据的读写支持。从文件目录操作,到文本文件读写,再到INI和XML等结构化数据的存取,Qt5都为我们准备了强大而方便的工具。


不过,Qt5对文件和数据的支持远不止如此。QFile还支持不同权限的文件操作、文件系统监视、内存文件等特性。QDataStream则让我们能在文件和内存之间高效传输原始字节数据。


此外,Qt5还内置了对JSON、压缩文件、资源文件等多种数据格式和文件类型的支持。而QtConcurrent模块也让我们能够轻松实现文件操作的异步和多线程。


那么,你是否已经迫不及待想在自己的应用中大展身手了呢?赶快行动起来,用Qt5的强大文件操作能力打造出属于自己的数据王国吧!如果在实践中有任何疑问,也别忘了及时在评论区留言,我将为你一一解答。让我们一起,在编程的海洋中继续扬帆远航!


03-24 17:37