#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; } }; |