批量替换文本工具(含源码)

 

批量替换文本工具(含源码)


 

程序下载:批量替换文本工具exe (请不要直接使用迅雷下载)

源代码下载:sourcecode.zip

注:VC6下编译通过

 

图片预览:

 

 

 

 

 

 


 

 

一、此工具可以批量替换多个文件中的多个文本。设有“全词匹配”和“区分大小写”2个选项。

 

 

二、如果程序有bug,望海涵并告知于我。qiujiejia@gmail.com Thank you!

 

 

三、把所有操作都封装在一个类CReplaceText里了,CFindStr是辅助用于不区分大小写搜索的。如果你有更好不区分大小写查找函数,请告知。谢谢!

 

四、调用如下:

 

 

CReplaceText test("d://a.cpp");
test.Replace("ii","tt",true,true);
// ii替换为tt, 第三参数true表示全词匹配,第四参数true表示需要区分大小写

//撤消操作
CReplaceText::Undo(szBuf);

 

 

五、CReplaceText源代码,具体请看程序源代码

 

 

#include <string>
using namespace std;

#ifdef _UNICODE
#define tsplitpath _wsplitpath
#else
#define tsplitpath _splitpath
#endif


/****************************************************************************
获取文件内容并放在一个string里
****************************************************************************/
BOOL GetFileString(const TCHAR* FilePath,string& str)
{
FILE* fp;
fp = fopen(FilePath, "rb");
if (!fp)
   return false;

//获取文件字符串个数
fseek(fp,0,SEEK_END);
UINT length=ftell(fp);
rewind(fp);

//获取文件文本
TCHAR* p;
p=new TCHAR[(length+1)*sizeof(TCHAR)];
fread(p,sizeof(TCHAR),length,fp);
p[length]=NULL;

str=p;

delete[] p;
fclose(fp);

return true;
}


/****************************************************************************
保存文件
****************************************************************************/
BOOL SaveFileString(const TCHAR* FilePath,string& str)
{
FILE* fp = fopen(FilePath, "wb");
if (!fp)
   return false;

return (str.size()==fwrite(str.c_str(),sizeof(TCHAR),str.size(),fp)) ?
   ( fclose(fp),true ) : ( fclose(fp),false ) ;
}

 

/****************************************************************************
不区分大小写搜索。我想不是最好的方法。将就着用吧
****************************************************************************/
class CFindStr
{
private:
static const TCHAR* src;
static TCHAR* FileString;
static TCHAR* FindText;
public:
static const TCHAR* pos;

static Initial(const TCHAR* str,const TCHAR* Find)
{
   src=str;
   FileString=_tcsupr(_tcsdup(str));
   FindText=_tcsupr(_tcsdup(Find));
   pos=FileString;
}
static finish()
{
   free(FileString);
   free(FindText);
}

static const TCHAR* FindNext()
{
   ASSERT(pos-FileString<=_tcslen(FileString));
   pos=_tcsstr(pos,FindText);
   return (pos==NULL) ? NULL : (pos-FileString+src);
}
};
const TCHAR* CFindStr::src;
TCHAR* CFindStr::FileString;
TCHAR* CFindStr::FindText;
const TCHAR* CFindStr::pos;


/****************************************************************************
CReplaceText 类可同时替换文件中的多个字符串
****************************************************************************/

class CReplaceText
{
string NewFile;
TCHAR m_FilePath[MAX_PATH];
BOOL IsModify;
public:
CReplaceText(const TCHAR* Path):
   IsModify(false)
{
   _tcscpy(m_FilePath,Path);
}
  
~CReplaceText()
{
   if (IsModify)
   {
    BOOL rel=FALSE;
    if (rel=BackupFile(m_FilePath))
     rel=SaveFileString(m_FilePath,NewFile) ;

/*
    //━━━━━━━━━━━━打印信息,g_EditWnd是一个Edit控件的句柄━━━━━
    TCHAR buf[1000]; TCHAR indi[]=_T("━━━━━━━━━━━━━━━━━━━━━━━━");
    _stprintf(buf,_T("/r/n%s/r/n文件: %s/r/n保存%s/r/n%s/r/n/r/n/r/n"),
     indi,m_FilePath,(rel?_T("成功"):_T("失败")),indi);
    ::SendMessage(g_EditWnd,EM_SETSEL,4294967290, 4294967290);   //光标指向最后
    ::SendMessage(g_EditWnd,EM_REPLACESEL,FALSE,(LPARAM)buf);    
    //━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
*/
   }
}

/****************************************************************************
恢复文件。函数会查找文件所在目录下是否有可用的备份并进行还原
****************************************************************************/
static int Undo(const TCHAR* FilePath)
{
   //获取备份文件的路径
   TCHAR NewFilePath[MAX_PATH]={0};
   TCHAR drive[_MAX_DRIVE];TCHAR dir[_MAX_DIR];TCHAR fname[_MAX_FNAME];TCHAR ext[_MAX_EXT];
   tsplitpath(FilePath, drive, dir, fname, ext );
   _tcscat(NewFilePath,drive);
   _tcscat(NewFilePath,dir);
   _tcscat(NewFilePath,_T("BackUpRelpaceFiles//"));
   _tcscat(NewFilePath,fname);
   _tcscat(NewFilePath,ext);

   if (-1==GetFileAttributes(NewFilePath))
    return -1;

   return CopyFile(NewFilePath,FilePath,false) ? 1:0;
}

/****************************************************************************
备份文件
****************************************************************************/
static BOOL BackupFile(const TCHAR* FilePath)
{
   TCHAR NewFilePath[MAX_PATH]={0};
   TCHAR drive[_MAX_DRIVE];TCHAR dir[_MAX_DIR];TCHAR fname[_MAX_FNAME];TCHAR ext[_MAX_EXT];
   tsplitpath(FilePath, drive, dir, fname, ext );
   _tcscat(NewFilePath,drive);
   _tcscat(NewFilePath,dir);
   _tcscat(NewFilePath,_T("BackUpRelpaceFiles//"));

   //假如NewFilePath文件夹不存在,则创建之
   if (-1==GetFileAttributes(NewFilePath))
    CreateDirectory(NewFilePath,NULL);

   _tcscat(NewFilePath,fname);
   _tcscat(NewFilePath,ext);

   return CopyFile(FilePath,NewFilePath,false);
}


/****************************************************************************
根据字符判断是否一个词
****************************************************************************/
BOOL IsWord(TCHAR p)
{
   if (('0'<=p && p<= '9' )
   || ( 'A'<=p && p<= 'Z' )
   || ( 'a'<=p && p<= 'z' )
   || ( '_'==p ) )
   {
    return true;
   }
   else
    return false;
}

/****************************************************************************
输入是常指针const TCHAR* OldString
输出是一个 string
很容易独立成一个函数
OldWord: 原来的文本
NewWord: 新的替换文本
IsMatchHoleWord: true-匹配整个词 false-不匹配
IsCase: true-区分大小写
****************************************************************************/
int Replace(const TCHAR* OldWord,const TCHAR* NewWord,BOOL IsMatchHoleWord=true,BOOL IsCase=true )
{
   const TCHAR* OldString;
   string FileString;

   if (NewFile.size()==0)
   {
    if (!GetFileString(m_FilePath,FileString))
    {
     return -1;
    }
   }
   else
   {
    FileString=NewFile;
    NewFile.resize(0); //清除NewFile
   }

   OldString=FileString.c_str();


   const TCHAR* pos=OldString;
   const TCHAR* LastPos=OldString;

   int ReplaceNum=0;    //累计替换的个数
   int OldWordLen=_tcslen(OldWord); //要替换词语的长度
  
   if (!IsCase)
    CFindStr::Initial(OldString,OldWord);

   while ( IsCase ? pos=_tcsstr(pos,OldWord) : pos=CFindStr::FindNext() )
   {
    //━━━━━━━━━━━━━━━━━━━━仅全词匹配━━━━━━━━━━━━━━
    if (IsMatchHoleWord==TRUE)
    {
     //pos必须大于字符串头,否则pos-1会出错
     if ( (pos>OldString && IsWord(*(pos-1))) || //判断替换词语的左边字符
      IsWord(*(pos+OldWordLen)))      //判断替换词语的右边字符
     {
     

      //重定位,不保存这次定位的指针
      if (!IsCase)
       CFindStr::pos+=OldWordLen;
      else
       pos+=OldWordLen;

      continue; //trace("是一个词"); //开始下一次搜索
     }
    }
    //━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
   
   
    //替换的个数
    ReplaceNum++;

   
/*
            //━━━━━━━━━━━━━━━━━━打印信息,g_EditWnd是一个Edit控件的句柄━━━━━
    //寻找pos左边第一个为/n的位置
    const TCHAR* p=pos;
    while((p--)>LastPos && *p!='/n');
    p++;
    //去掉左边的空格和TAB
    while( (*p==' ' || *p=='/t') && (p++)<pos ) ;
    //_tcschr(pos,'/r')指向pos右边第一个为/r的位置
    int num=_tcschr(pos,'/r')-p;
    if (num<0)   num=0;
    TCHAR line[100];
    _tcsncpy(line,p,num);
    line[(num<99?num:99)]=NULL;
            TCHAR buf[300];
            _stprintf(buf,_T("%d/t替换了:%s 原来行:%s/r/n"),ReplaceNum,OldWord,line);
            ::SendMessage(g_EditWnd,EM_SETSEL,4294967290, 4294967290);   //光标指向最后
            ::SendMessage(g_EditWnd,EM_REPLACESEL,FALSE,(LPARAM)buf);    
    //━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
*/
   
   
    //insert strings to NewFile
    NewFile.append(LastPos,pos-LastPos);
    NewFile+=NewWord;
   
    //重定位,并且保存这次定位的指针为LastPos
    if (!IsCase)
    {
     CFindStr::pos+=OldWordLen;
     LastPos=pos+OldWordLen;
    }
    else
    {
     pos+=OldWordLen;
     LastPos=pos;
    }
   }
  
   //补上最后的文本
   NewFile+=LastPos;

   if (ReplaceNum!=0)
    IsModify=true;

   //删除由_tcsdup创建的字符串
   if (!IsCase)
    CFindStr::finish();

/*
   //━━━━━━━━━━━━打印信息,g_EditWnd是一个Edit控件的句柄━━━━━
        TCHAR buf[500];
        _stprintf(buf,_T("文件:%s/r/n一共替换了: /"%s/" %d个/r/n/r/n"),m_FilePath,OldWord,ReplaceNum);
        ::SendMessage(g_EditWnd,EM_SETSEL,4294967290, 4294967290);   //光标指向最后
        ::SendMessage(g_EditWnd,EM_REPLACESEL,FALSE,(LPARAM)buf);    
        //━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
*/


   return ReplaceNum;
}
};

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值