将一个目录下所有指定文件里面的特定字符串替换

时间:2021-09-17 23:28:57

  这是曾经写的一个程序,目的很简单就是把自己以前完成的一个工程里面特定字符串替换,本来用脚本是很简单的,但是当时还未接触只得用VC写了一个程序,可以看出有多么麻烦!!。
  程序涉及到知识点: 指针 链表 文件遍历 内存映射文件,代码如下

// Test2.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "windows.h"

#define MAC_FILENAMELENOPATH 50

typedef struct  Node {
        Node    *next;
        char    Name[256];
}Node;


void    FindFileInDir(char* rootDir);
void    AddToChain(Node *pTempNode);
void    FreeMem(void );
bool    IsFile(char *Name);
void    HandleFile(char *Name);
void    Temp();

char        SouceString[256],DestString[256];
char        * strPath = "f:\\WorkPlace\\005";           ///工程所在的目录
Node        *Head,*Tail;


char    *src[] ={"abcdef",NULL };               ///源字符串
char    *dest[]={"GDEGEF",NULL};                ///要替换成的字符串


int main(/*int argc, char *argv[]*/)
{
    int i,j;

    for (i = 0;src[i];i ++)
    {
        strcpy(SouceString,src[i]);
        strcpy(DestString ,dest[i]);

        Temp();
    }
    return 0;
}

void    Temp()
{
    Node    *pTemp;
    Head    = Tail  = NULL;

    FindFileInDir(strPath);             /// 此函数执行完时, Head Tail 链表里面已经有了存储内容。

    pTemp   = Head;

    while(1)
    {
        if(pTemp == NULL)
        {
            break;
        }
        if(IsFile(pTemp->Name))
        {
            HandleFile(pTemp->Name);
        }
        pTemp   = pTemp->next ;
    }

    FreeMem();
}

void FindFileInDir(char* rootDir)
{
    char    fname[MAC_FILENAMELENOPATH];    
    ZeroMemory(fname, MAC_FILENAMELENOPATH);

    WIN32_FIND_DATA fd;
    ZeroMemory(&fd, sizeof(WIN32_FIND_DATA));

    HANDLE hSearch;
    char filePathName[256];
    char tmpPath[256];

    ZeroMemory(filePathName, 256);
    ZeroMemory(tmpPath, 256);

    Node    *pTempNode;

    strcpy(filePathName, rootDir);

    BOOL bSearchFinished = FALSE;

    if( filePathName[strlen(filePathName) -1] != '\\' )
    {
        strcat(filePathName, "\\");
    }

    strcat(filePathName, "*");

    hSearch = FindFirstFile(filePathName, &fd);

    //Is directory
    if( (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
        && strcmp(fd.cFileName, ".") && strcmp(fd.cFileName, "..") )        
    {
        strcpy(tmpPath, rootDir);
        strcat(tmpPath,"\\");
        strcat(tmpPath, fd.cFileName);
        FindFileInDir(tmpPath);
    }

    else    if( strcmp(fd.cFileName, ".") && strcmp(fd.cFileName, "..") )
    {
        pTempNode   = (Node *)VirtualAlloc(NULL, /// 分配内存区域的地址。当你使用VirtualAlloc来提交一块以前保留的内存块的时候,
                          //lpAddress参数可以用来识别以前保留的内存块。
                          ///如果这个参数是NULL,系统将会决定分配内存区域的位置,并且按64-KB向上取整(roundup)。 
                        //内存保留提交映射 三部曲(windows核心编程)
                sizeof(Node),   //要分配或者保留的区域的大小。这个参数以字节为单位,而不是页,
                        //系统会根据这个大小一直分配到下页的边界DWORD 
                MEM_COMMIT, //分配指定 保留 的内存页
                PAGE_READWRITE);      
        strcpy(pTempNode->Name ,rootDir);
        strcat(pTempNode->Name ,"\\");
        strcat(pTempNode->Name ,fd.cFileName );
        pTempNode->next     = NULL;
        AddToChain(pTempNode);
    }

    while( !bSearchFinished )
    {
        if( FindNextFile(hSearch, &fd) )
        {
            //Is directory
            if( (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
                && strcmp(fd.cFileName, ".") && strcmp(fd.cFileName, "..") )        
            {
                strcpy(tmpPath, rootDir);
                strcat(tmpPath,"\\");
                strcat(tmpPath, fd.cFileName);
                FindFileInDir(tmpPath);
            }   
            else if( strcmp(fd.cFileName, ".") && strcmp(fd.cFileName, "..") )
            {
                pTempNode   = (Node *)VirtualAlloc(NULL, sizeof(Node),  MEM_COMMIT, PAGE_READWRITE);      
                strcpy(pTempNode->Name ,rootDir);
                strcat(pTempNode->Name ,"\\");
                strcat(pTempNode->Name ,fd.cFileName );
                pTempNode->next     = NULL;
                AddToChain(pTempNode);
            }
        }
        else
        {
            if( GetLastError() == ERROR_NO_MORE_FILES )         //Normal Finished
            {
                bSearchFinished = TRUE;
            }
            else
                bSearchFinished = TRUE;     //Terminate Search
        }
    }
    FindClose(hSearch);
}

///将一个节点增加到 链表上。
void    AddToChain(Node *pNode)
{
    if(Head == NULL )
    {
        Head    = Tail  = pNode;
    }
    else
    {
        Tail->next  = pNode;
        Tail        = pNode;
    }
}

///释放链表中内存
void    FreeMem(void )
{
    Node    *pTemp;
    if(Head == NULL)
        return ;
    pTemp   = Head->next ;
    while(1)
    {
        VirtualFree(Head,sizeof(Node),MEM_DECOMMIT);
        Head    = pTemp;
        pTemp   = Head->next ;
        if(pTemp == NULL)
        {
            break;
        }
    }
}

///判断是否是指定的文件 .c 或者 .h。
bool    IsFile(char *Name)
{
    char    *pTemp;

    pTemp   = Name + strlen(Name);
    while(*pTemp != '\\')
    {
        pTemp --;
    }

    pTemp   = strstr(Name,".");
    if(pTemp == NULL)
    {
        return FALSE;
    }
    if( (strcmp(pTemp,".c") == 0)   ||
        (strcmp(pTemp,".h") == 0)   )
    {
        return TRUE;    
    }
    return FALSE;
}

///对于指定的文件打开,替换字符串
///对于替换字符串有一个规律:
///DestString长度要比SouceString要短。
void    HandleFile(char *Name)
{
    HANDLE      hFile;
    LPTSTR      hMap;
    LPTSTR      lpMapAddr;
    char        *pTemp;
    char        *pStr;
    int         Len,LenDest;
    int         i;

    hFile       = CreateFile(Name,                      
                    GENERIC_READ |GENERIC_WRITE ,           // 表示允许对设备进行读写访问;(组合)
                    0,                                      //dwShareMode Long,零表示不共享; FILE_SHARE_READ/WRITE 表示允许对文件进行共享访问 
                    NULL,                                   //指向一个SECURITY_ATTRIBUTES结构的指针,定义了文件的安全特性
                    OPEN_EXISTING ,                         //OPEN_EXISTING 文件必须已经存在。由设备提出要求 
                    FILE_ATTRIBUTE_NORMAL,                  //dwFlagsAndAttributes Long,FILE_ATTRIBUTE_NORMAL 默认属性 
                    0 );                                    //hTemplateFile Long,如果不为零,则指定一个文件句柄。新文件将从这个文件中复制扩展属性
    hMap        = (LPTSTR)CreateFileMapping(hFile,          // 一个文件句柄
                    NULL,                                   //定义内存映射文件对象是否可以被承
                    PAGE_READWRITE,                         //该内存映射文件的保护类型
                    0,                                      // 内存映射文件的长度 高位
                    GetFileSize(hFile, NULL),               // 内存映射文件的长度 低位
                    "MyMap");                               // 内存映射文件的名字
    lpMapAddr   = (LPTSTR)MapViewOfFile(hMap,FILE_MAP_ALL_ACCESS, 0,0,0);

    Len         = strlen(SouceString);
    LenDest     = strlen(DestString);

    pStr        = (char *)lpMapAddr;
    i           = 0;

    while(1)
    {
        pTemp   = strstr((char *)pStr,SouceString);
        if(pTemp == NULL)
            break;
        memset(pTemp,9,Len);                                // IDE 集成环境里面 空格字符ASCII码是 9
        for(i=0;i < LenDest;i ++)
        {
            *pTemp  ++ = DestString[i];
        }
        pStr    = pTemp + Len;
    }

    UnmapViewOfFile(lpMapAddr);
    CloseHandle(hMap);
    CloseHandle(hFile);
}

作为对比可见相同功能的博文: 几行代码就搞定了!
使用python 修改文件内容