文件内容替换---郁闷的结果

今天要写一个批量替换文件某一行内容的小程序,

开始的想法是直接在文件里操作(不生成新文件),于是写下如下代码(对单个文件操作)

  1. /* 
  2. string m_strRepSrc;//被替换行中的标识字符串 vc98/include/
    string m_strRepDes;//替换成的字符串 F:/Program Files/software/Microsoft Visual Studio 8/VC/include/
    •             
    •             要求效果:
    •             "e:/program files/microsoft visual studio/vc98/include/basetsd.h"/
    •             修改成==>
    •             "F:/Program Files/software/Microsoft Visual Studio 8/VC/include/basetsd.h"/
    •             其中basetsd.h"/要求不变
  3. */
  4. bool CReplace::deal()
  5. {
  6.     //打开文件 
  7.     CStdioFile hFile(m_strFilePath.c_str(), CFile::modeReadWrite|CFile::shareDenyWrite);
  8.     //查找 
  9.     CString strTemp;
  10.     CString newStr;
  11.     LONG iIdx = 0;
  12.     while (hFile.ReadString(strTemp))
  13.     {
  14.         iIdx = strTemp.Find(m_strRepSrc.c_str()); //如果行中含有标识字符串则进入替换
  15.         if (iIdx != -1)
  16.         {      
  17.             //获取不替换部分; 
  18.             newStr = strTemp.Right(strTemp.GetLength() - iIdx - 1 - m_strRepSrc.length()); //basetsd.h"/
  19.             //替换成的字符串 
  20.             newStr = CString(_T("/"")) + CString(m_strRepDes.c_str()) + newStr + CString(_T("/n"));
  21.             //写回文件 
  22.             
  23.             hFile.Seek(-2-strTemp.GetLength(), CFile::current); //找到被替换字符串的起始位置 
  24.             hFile.WriteString(newStr.GetBuffer());
  25.             newStr.ReleaseBuffer();
  26.         
  27.         }
  28.     }
  29.     hFile.Close();
  30.     
  31.     return true;
  32. }

结果程序一执行,不如人意,由于

"F:/Program Files/software/Microsoft Visual Studio 8/VC/include/basetsd.h"/ 长度要比

"e:/program files/microsoft visual studio/vc98/include/basetsd.h"/

导致文件中"e:/program files/microsoft visual studio/vc98/include/basetsd.h"/后面的内容被覆盖

之后由于

hFile.Seek(-2-strTemp.GetLength(), CFile::current); 

hFile.WriteString(newStr.GetBuffer());

的原因,导致hFile.ReadString读回前面的内容了,从而死循环

并且使目标文件增大了数倍(把前面的内容写进来了)....汗   ====>这里不明白为什么会把文件前面的内容写进来了...

 

结论:普通方法不能在一个文件里面直接替换文件内容,除非替换与被替换的字符串长度一样

长度一样的话,如下就可以实现

  1.             lPos = hFile.GetPosition();
  2.             hFile.Seek(-2-strTemp.GetLength(), CFile::current);
  3.             hFile.WriteString(newStr.GetBuffer());
  4.             newStr.ReleaseBuffer();
  5.             hFile.Seek(lPos, CFile::begin);

最终,换方法,把文件内容读入内存,在内存中替换文件内容,然后写回文件...

实现如下
  1. //将strBig中所有的strsrc替换成strdst
  2. void CReplace::string_replace(string & strBig, const string & strsrc, const string &strdst) 
  3. {
  4.         string::size_type pos=0;
  5.         string::size_type srclen = strsrc.size();
  6.         string::size_type dstlen = strdst.size();
  7.         while((pos=strBig.find(strsrc, pos)) != string::npos)
  8.         {
  9.             strBig.replace(pos, srclen, strdst); //从索引pos开始的srclen个字符替换成后面的strdst
  10.             pos += dstlen;
  11.         }
  12. }
  13. bool CReplace::deal()
  14. {
  15.     ifstream in(m_strFilePath.c_str());
  16.     stringstream ss;
  17.     ss << in.rdbuf();
  18.     string s = ss.str();
  19.     //size_type类型为unsigned型,与具体机器有关
  20.     string::size_type iIdx=0;
  21.     string::size_type iBegin, iEnd;
  22.     iIdx = s.find(m_strRepSrc);
  23.     if (iIdx != string::npos)
  24.     {
  25.         iBegin = s.rfind("/"", iIdx);
  26.         iEnd = iIdx + m_strRepSrc.size();
  27.         string sRep = s.substr(iBegin, iEnd-iBegin);
  28.         //s.replace(sRep, m_strRepDes);
  29.         string_replace(s, sRep, m_strRepDes);
  30.         //写回
  31.         ofstream out(m_strFilePath.c_str());
  32.         out << s;
  33.         //不需要out.close(),scope结束out析构会自动close()
  34.     }
  35.     in.close();
  36.     
  37.     return true;
  38. }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值