前言

一开始在做linux下的qt相关开发时,经常重复着灵活快速的修改文件中的某个内容,所以特此记录,下次直接复制粘贴代码。

思路是,先读取文件中的内容存在QString中,然后提取出我们要修改的那一段内容,这时候就变成了替换字符串中特定内容的问题了。再通过正则表达式和对字符串的控制,修改想要修改的内容。因为情况不同,代码的具体写法也不一致,但我们只要处理了核心步骤,修改文件中的内容,甚至是修改字符串中的某个内容这些问题都能迎刃而解了。下面以这个案例为例。

案例:
img

该文件是nginx服务的配置文件,需要做的是替换文件中 listen后的的端口号

先上代码:

	QFile fileRead(filePath);       //先读取文件信息,QIODevice::Text能将换行转为\n
    QString arryRead;
    if(fileRead.open(QIODevice::ReadOnly|QIODevice::Text)){
        arryRead= fileRead.readAll();
    }
    fileRead.close();
    qDebug()<<"arryRead"<<arryRead;

    QStringList arryListWrite= arryRead.split("\n");        //存储每一段信息
    qDebug()<<"arryListWrite:";
    for(int i=0;i<arryListWrite.size();i++){
        qDebug()<<arryListWrite.at(i);
    }

    QFile fileWrite(filePath);
    if(fileWrite.open(QIODevice::WriteOnly|QIODevice::Text)){        //文件流写文件
        QTextStream streamWrite(&fileWrite);      //通过文本流控制文件写操作

        for(int i=0;i<arryListWrite.size()-1;i++){      //这里到arryListWrite.size()-1是因为arryListWrite数组按照\n分 段时,最后一行尾部有个\n,所以数组最后一个值为空,需要将它去掉

            if(arryListWrite.at(i).contains(keyword)){

                contentWrite.replace();		//-----替换端口号的代码,难点在于replace方法的实现,此处的代码下面给出

                streamWrite<<contentWrite<<"\n";
            }else{
                streamWrite<<arryListWrite.at(i)<<"\n";
            }
        }
    }
    fileWrite .close();

该代码的基本思路如下:

  1. QFile类读取文件中的内容,并分段存储到arryListWrite数组中
  2. 对每一段进行筛查,如果含有listen,则这段是我们需要的
  3. 使用replace方法,替换掉8899这个端口号,使用replace方法时我们需要确定8899中首个数字的位置和这个端口号的长度(因为端口号是0-65535,所以还不能直接确定端口号的长度就是4),使用indexof()方法来确定
  4. 最后使用QTextStream文本流写入文件

listen 8899;

1、2和4比较简单,问题出在3,3灵活写好,就可以封装出替换掉文件中任意想要替换的内容,所以下面主要介绍第3步的实现

方法一,通过字符串处理实现replace方法,这是比较笨的方法,后来发现使用正则表达式来替换字符则更方便更灵活

replace方法:
QString &QString::replace(int position, int n, const QString &after)
    //position为替换字符的索引值,n为要替换的长度,after为替换后的字符

思路:确定listen首字母的位置,确定最后";"的位置上,计算端口号的长度

	QString contentWrite= arryListWrite.at(i);		//获取包含关键字的那一行字符

	int indexBefore=contentWrite.indexOf(keyword);
	contentWrite.replace(indexBefore+keyword.length(),contentWrite.size()-indexBefore-keyword.length()-after_reduceLength,replaceContent);

如下是我自己封装的方法:

void MainWindow::modify_file_content(QString filePath,QString keyword,QString replaceContent,int after_reduceLength)
{
    QFile fileRead(filePath);       //先读取文件信息,QIODevice::Text能将换行转为\n
    QString arryRead;
    if(fileRead.open(QIODevice::ReadOnly|QIODevice::Text)){
        arryRead= fileRead.readAll();
    }
    fileRead.close();
    qDebug()<<"arryRead"<<arryRead;

    QStringList arryListWrite= arryRead.split("\n");        //存储每一段信息
    qDebug()<<"arryListWrite:";
    for(int i=0;i<arryListWrite.size();i++){
        qDebug()<<arryListWrite.at(i);
    }

    QFile fileWrite(filePath);
    if(fileWrite.open(QIODevice::WriteOnly|QIODevice::Text)){        //文件流写文件
        QTextStream streamWrite(&fileWrite);      //通过文本流控制文件写操作

        for(int i=0;i<arryListWrite.size()-1;i++){      //这里到arryListWrite.size()-1是因为arryListWrite数组按照\n分 段时,最后一行尾部有个\n,所以数组最后一个值为空,需要将它去掉

            if(arryListWrite.at(i).contains(keyword)){

                QString contentWrite= arryListWrite.at(i);
                
                //-----读者可自行替换内容
                int indexBefore=contentWrite.indexOf(keyword);
                contentWrite.replace(indexBefore+keyword.length(),contentWrite.size()-indexBefore-keyword.length()-after_reduceLength,replaceContent);
                //-----读者可自行替换内容

                streamWrite<<contentWrite<<"\n";
            }else{
                streamWrite<<arryListWrite.at(i)<<"\n";
            }
        }
    }
    fileWrite .close();
}

方法二,通过正则表达式,来判断这段字符中的端口号的位置,再调用replace方法。

replace方法:
QString &QString::replace(QChar before, QChar after, Qt::CaseSensitivity cs = Qt::CaseSensitive)
    //before为要被替换的内容,after为替换后的内容,第三个参数可不填

正则表达式理论上可以匹配,替换任意你想要的的字符

		QString contentWrite= arryListWrite.at(i);		//获取包含关键字的那一行字符

		QRegExp regexp("listen (\\d*);");
		regexp.indexIn(contentWrite,0);
		qDebug()<<regexp.cap(1);
		contentWrite.replace(regexp.cap(1),replaceContent);

该方法的完整代码:

void MainWindow::modify_file_content_RegExp(QString filePath, QString keyword, QString replaceContent)
{
    QFile fileRead(filePath);       //先读取文件信息,QIODevice::Text能将换行转为\n
    QString arryRead;
    if(fileRead.open(QIODevice::ReadOnly|QIODevice::Text)){
        arryRead= fileRead.readAll();
    }
    fileRead.close();
    qDebug()<<"arryRead"<<arryRead;

    QStringList arryListWrite= arryRead.split("\n");        //存储每一段信息
    qDebug()<<"arryListWrite:";
    for(int i=0;i<arryListWrite.size();i++){
        qDebug()<<arryListWrite.at(i);
    }

    QFile fileWrite(filePath);
    if(fileWrite.open(QIODevice::WriteOnly|QIODevice::Text)){        //文件流写文件
        QTextStream streamWrite(&fileWrite);      //通过文本流控制文件写操作

        for(int i=0;i<arryListWrite.size()-1;i++){      //这里到arryListWrite.size()-1是因为arryListWrite数组按照\n分 段时,最后一行尾部有个\n,所以数组最后一个值为空,需要将它去掉

            if(arryListWrite.at(i).contains(keyword)){

                QString contentWrite= arryListWrite.at(i);

                //-----读者可自行替换内容
                QRegExp regexp("listen (\\d*);");
                regexp.indexIn(contentWrite,0);
                qDebug()<<regexp.cap(1);
                contentWrite.replace(regexp.cap(1),replaceContent);
                //-----读者可自行替换内容

                streamWrite<<contentWrite<<"\n";
            }else{
                streamWrite<<arryListWrite.at(i)<<"\n";
            }
        }
    }
    fileWrite .close();
}

关于正则表达式的一些介绍:

链接:常用正则表达式介绍

链接:QT QRegExp 正则匹配、查找、替换的方法小案例

正则表达式的内容较多,熟练掌握后可以提取,替换,删除任意字符串。爬虫中就运用这种思路。

注意:c++中的正则表达式\要换成\\,很多资料都没有提及

调用上述封装的方法:

	modify_file_content("/root/test_file.txt","listen ","9911",1);
    modify_file_content_RegExp("/root/test_file.txt","listen ","9911");

注意:windows中文件路径单反斜杠要换成双反斜杠,linux中要注意文件读写权限的问题,否则都将导致修改不成功

码字不易,如果这篇博客对你有帮助,麻烦点赞收藏,非常感谢!有不对的地方,可以评论区交流。

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐