前言
一开始在做linux下的qt相关开发时,经常重复着灵活快速的修改文件中的某个内容,所以特此记录,下次直接复制粘贴代码。
思路是,先读取文件中的内容存在QString中,然后提取出我们要修改的那一段内容,这时候就变成了替换字符串中特定内容的问题了。再通过正则表达式和对字符串的控制,修改想要修改的内容。因为情况不同,代码的具体写法也不一致,但我们只要处理了核心步骤,修改文件中的内容,甚至是修改字符串中的某个内容这些问题都能迎刃而解了。下面以这个案例为例。
案例:
该文件是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();
该代码的基本思路如下:
- QFile类读取文件中的内容,并分段存储到arryListWrite数组中
- 对每一段进行筛查,如果含有listen,则这段是我们需要的
- 使用replace方法,替换掉8899这个端口号,使用replace方法时我们需要确定8899中首个数字的位置和这个端口号的长度(因为端口号是0-65535,所以还不能直接确定端口号的长度就是4),使用indexof()方法来确定
- 最后使用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中要注意文件读写权限的问题,否则都将导致修改不成功
码字不易,如果这篇博客对你有帮助,麻烦点赞收藏,非常感谢!有不对的地方,可以评论区交流。