如何用Qt替换.txt文件中特定行的文本?

时间:2016-04-17 17:43:18

标签: qt

我有这个“data.txt”里面有这个文字:

1;Bob;Patino;43
/2;Chris;Metsen;46
/3;Rob;Pardo;37
/4;Megan;Fox;25
/5;Cara;Delevingne;21

我想用“Metzen”替换第二行“Metsen”的文本。 我可以通过重写整个数据来做到这一点,这很容易,但可能不方便大量的数据。

有没有办法通过重写特定数据(理想情况下使用QFileQTextStream)来实现?

1 个答案:

答案 0 :(得分:2)

从你的问题来看,你想要在内存映射IO中进行替换,这在一般情况下是不可能的。如果文件没有ASCII编码,或者替换文本的大小与它替换的文本大小相同,会发生什么?只要您需要插入'无论你喜不喜欢,你都在重写整个文件。此外,文件仍然必须完全读取才能搜索文本,因此无论如何它最终都不会成为优化。现代磁盘驱动器的写入速度为每秒数百到数千兆字节,因此您的写入时间可能可以忽略不计。

更不用说在尝试调试程序时,几乎100%肯定会破坏原始数据。即使你做得对,如果这个过程死了,你也会破坏原始数据。这不是正确的方法。

也就是说,使用QFileQTextStream的正则表达式可以执行简单的子串替换 。该程序读入data.txt,更正拼写错误,并将结果写入名为newData.txt的新文件。

#include <QFile>
#include <QRegularExpression>
#include <QRegularExpressionMatch>
#include <QRegularExpressionMatchIterator>
#include <QTextStream>

int main(int argc, char *argv[])
{
    QFile data("C:/workspace/simpleQtProject/data.txt");
    data.open(QIODevice::Text | QIODevice::ReadOnly);
    QString dataText = data.readAll();

    QRegularExpression re("Metsen");
    QString replacementText("Metzen");

    dataText.replace(re, replacementText);

    QFile newData("C:/workspace/simpleQtProject/newData.txt");
    if(newData.open(QFile::WriteOnly | QFile::Truncate)) {
        QTextStream out(&newData);
        out << dataText;
    }
    newData.close();

    return 0;
}

注意: QRegularExpression的优化性能实际上非常好,但由于在调试模式下禁用了JIT编译器,因此调试可能会很慢。有关实施的细微差别(以及发布性能的基准)的详细讨论,请参见peppe's blog post

此外,如果您的正则表达式变得更复杂,并且您需要更好地控制替换的执行方式,则可以使用QRegularExpressionMatchIterator语法和基于索引的QString::replace() 。这可以支持多个或命名的捕获组,或其他高级正则表达式功能。

#include <QFile>
#include <QRegularExpression>
#include <QRegularExpressionMatch>
#include <QRegularExpressionMatchIterator>
#include <QTextStream>

int main(int argc, char *argv[])
{
    QFile data("C:/workspace/simpleQtProject/data.txt");
    data.open(QIODevice::Text | QIODevice::ReadOnly);
    QString dataText = data.readAll();

    // Using regex match iterator. Overkill for simple substring replacement, but scalable
    // to very complex replacements.
    QRegularExpression re("Metsen");
    QString replacementText("Metzen");

    QRegularExpressionMatchIterator itr = re.globalMatch(dataText);

    while(itr.hasNext())
    {
        QRegularExpressionMatch match = itr.next();
        dataText.replace(match.capturedStart(0), match.capturedLength(0), replacementText);
    }

    QFile newData("C:/workspace/simpleQtProject/newData.txt");
    if(newData.open(QFile::WriteOnly | QFile::Truncate)) {
        QTextStream out(&newData);
        out << dataText;
    }
    newData.close();

    return 0;
}