这是曾经写的一个程序,目的很简单就是把自己以前完成的一个工程里面特定字符串替换,本来用脚本是很简单的,但是当时还未接触只得用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 修改文件内容