在实际的软件开发项目中,大家也许会遇到修改文件的后缀的需求(例如,将doc格式修改为docx格式)。本文提供了修改文件后缀的C语言实现,并演示了修改文件后缀的过程。
1. C程序实现
/**********************************************************************
* 版权所有 (C)2014, ZhouZhaoxiong。
*
* 文件名称: ChangeSuffix.c
* 文件标识:无
* 内容摘要:对文件的后缀进行转换
* 其它说明:无
* 当前版本: V1.0
* 作 者:周兆熊
* 完成日期: 20141117
**********************************************************************/
#include
#include
#include
#include
#include
#defineMAX_FILESUFFIX_NUM 10 // 能够配置的文件后缀最大个数
#defineMAX_FILESUFFIX_LEN 10 // 单个文件后缀的最大长度
#define _MAXPATH 1024
int GetAppConfig(void);
voidParseFileSuffix(char *pSzSuffixBuf, int iType);
int GetFileExt(char*pFilePath, char *pOutFileExt);
int main(int argc, char*argv[]);
void Check(char*pPath);
voidModifyFileName(char* pFilePath, char *pFileName);
// 全局配置
typedef struct
{
int iOld2NewOrNew2Old; // 新老后缀的转换
charszOldSuffix[MAX_FILESUFFIX_NUM][MAX_FILESUFFIX_LEN]; // 旧的文件后缀
charszNewSuffix[MAX_FILESUFFIX_NUM][MAX_FILESUFFIX_LEN]; // 新的文件后缀
} Config_T;
Config_T g_tConfig;
/****************************************************************
* 功能描述: 获取全局配置
* 输入参数: 无
* 输出参数: 无
* 返 回 值: 0-执行成功 -1-执行失败
* 其它说明:无
* 修改日期 版本号 修改人 修改内容
*--------------------------------------------------------------
* 20141117 V1.0 zzx 新建
****************************************************************/
int GetAppConfig(void)
{
char szIniFile[128] ={0};
char szOldSuffix[256] = {0};
char szNewSuffix[256] = {0};
memset(&g_tConfig, 0x00,sizeof(Config_T));
GetCurrentDirectory(sizeof(szIniFile)-1,szIniFile);
strcat(szIniFile, "\\");
strcat(szIniFile, "Config.ini");
// 读取各个配置的值
// 获取新旧后缀的转换标志
g_tConfig.iOld2NewOrNew2Old =GetPrivateProfileInt("General", "Old2NewOrNew2Old", 1,szIniFile);
// 获取旧的后缀并解析
GetPrivateProfileString("General", "OldSuffix","", szOldSuffix, sizeof(szOldSuffix), szIniFile);
if (strlen(szOldSuffix) == 0)
{
return -1;
}
ParseFileSuffix(szOldSuffix, 1);
// 获取新的后缀并解析
GetPrivateProfileString("General", "NewSuffix","", szNewSuffix, sizeof(szNewSuffix), szIniFile);
if (strlen(szNewSuffix) == 0)
{
return -1;
}
ParseFileSuffix(szNewSuffix, 2);
return 0;
}
/****************************************************************
* 功能描述: 对读取到的后缀配置进行解析
* 输入参数: pSzSuffixBuf: 包含所有配置值的缓存
iType:解析新旧后缀的标志
* 输出参数: 无
* 返 回 值: 无
* 其它说明:无
* 修改日期 版本号 修改人 修改内容
*--------------------------------------------------------------
* 20141117 V1.0 zzx 新建
****************************************************************/
void ParseFileSuffix(char*pSzSuffixBuf, int iType)
{
char szFileSuffix[128] = {0};
char *t = NULL;
char *p = NULL;
int h = 0;
int iLen = 0;
int iCpLen = 0;
if (pSzSuffixBuf == NULL)
{
return;
}
memcpy(szFileSuffix, pSzSuffixBuf,sizeof(szFileSuffix));
iLen = strlen(szFileSuffix);
if (iLen >= sizeof(szFileSuffix))
{
iLen = sizeof(szFileSuffix);
}
if (szFileSuffix[iLen-1] != ';')
{
strcat(szFileSuffix, ";");
}
t = szFileSuffix;
while ((p=strchr(t, ';')) != NULL)
{
if ((p-t) >= MAX_FILESUFFIX_LEN)
{
iCpLen = MAX_FILESUFFIX_LEN;
}
else
{
iCpLen = p-t;
}
switch (iType)
{
case 1: // 解析旧的后缀
{
strncpy(g_tConfig.szOldSuffix[h], t, iCpLen);
break;
}
case 2: // 解析新的后缀
{
strncpy(g_tConfig.szNewSuffix[h], t, iCpLen);
break;
}
default:
{
break;
}
}
t = p + 1;
h ++;
if (h >= MAX_FILESUFFIX_NUM)
{
break;
}
}
return;
}
/****************************************************************
* 功能描述: 获取文件后缀
* 输入参数: pFilePath-包含路径的文件名
* 输出参数: pOutFileExt-文件后缀
* 返 回值: 0-执行成功 -1-执行失败
* 其它说明:无
* 修改日期 版本号 修改人 修改内容
*--------------------------------------------------------------
* 20141117 V1.0 zzx 新建
****************************************************************/
int GetFileExt(char*pFilePath, char *pOutFileExt)
{
char *pDest = NULL;
int iResult = 0;
int iFullPathLen = 0;
int iFileExtLen = 0;
char szFullPathName[_MAXPATH] = {0};
if ((NULL == pFilePath) || (NULL == pOutFileExt))
{
return -1;
}
_snprintf(szFullPathName,sizeof(szFullPathName)-1, "%s", pFilePath);
iFullPathLen = strlen(szFullPathName);
pDest = strrchr(szFullPathName, '.');
if (NULL == pDest)
{
return -1;
}
iResult = pDest - szFullPathName + 1;
iFileExtLen = iFullPathLen - iResult;
if (iFileExtLen > 0)
{
memcpy(pOutFileExt, szFullPathName+iResult,iFileExtLen);
}
else
{
*pOutFileExt = 0;
}
return 0;
}
/****************************************************************
* 功能描述: 修改文件后缀
* 输入参数: pFilePath-文件路径
* 输出参数: pOutFileExt-文件后缀
* 返 回 值: TRUE-执行成功 FALSE-执行失败
* 其它说明:无
* 修改日期 版本号 修改人 修改内容
*--------------------------------------------------------------
* 20141117 V1.0 zzx 新建
****************************************************************/
voidModifyFileName(char* pFilePath, char *pFileName)
{
HANDLE hFile = NULL;
int iLoopFlag = 0;
int iResult = 0;
int iNameLen = 0;
int iTotalExtType = 0;
char szFileTitle[_MAXPATH] = {0};
char szFilename[_MAXPATH] = {0};
char szNewFilename[_MAXPATH] = {0};
char szFileExt[_MAXPATH] = {0};
if((NULL == pFilePath) || (NULL == pFileName))
{
return;
}
if (-1 == GetFileExt(pFileName, szFileExt))
{
return;
}
printf("ext:[%s] file:[%s]\n", szFileExt,pFileName);
iNameLen = strlen(pFileName)-strlen(szFileExt);
memcpy(szFileTitle, pFileName, iNameLen);
iTotalExtType = sizeof(g_tConfig.szOldSuffix) /sizeof(g_tConfig.szOldSuffix[0]);
for (iLoopFlag = 0; iLoopFlag = iTotalExtType)
{
printf("非修改文件类型: %s\n", szFileExt);
return;
}
_snprintf(szFilename, sizeof(szFilename)-1,"%s\\%s", pFilePath, pFileName);
if (1 == g_tConfig.iOld2NewOrNew2Old) // 变为新的后缀
{
_snprintf(szNewFilename, sizeof(szNewFilename)-1,"%s\\%s%s", pFilePath, szFileTitle, g_tConfig.szNewSuffix[iLoopFlag]);
}
else
{
_snprintf(szNewFilename, sizeof(szNewFilename)-1,"%s\\%s%s", pFilePath, szFileTitle,g_tConfig.szOldSuffix[iLoopFlag]);
}
iResult = rename(szFilename,szNewFilename);
if (iResult != 0)
{
printf("Could not rename'%s'\n", szFilename);
}
else
{
printf("File '%s' renamed to'%s'\n", szFilename, szNewFilename);
}
return;
}
/****************************************************************
* 功能描述: 扫描文件目录
* 输入参数: pPath-文件路径
* 输出参数: 无
* 返回值: TRUE-执行成功 FALSE-执行失败
* 其它说明:无
* 修改日期 版本号 修改人 修改内容
*--------------------------------------------------------------
* 20141117 V1.0 zzx 新建
****************************************************************/
void Check(char *pPath)
{
struct _finddata_t hFile; //定义结构体变量
long handle;
char szPath[_MAXPATH] = {0};
memset(szPath, 0, sizeof(szPath));
_snprintf(szPath, sizeof(szPath)-1, "%s\\*", pPath);
handle =_findfirst(szPath, &hFile); // 查找所有文件
if (handle == -1)
{
printf("目录 %s 为空\n", pPath);
return;
}
else
{
if (hFile.attrib &_A_SUBDIR) // 是目录
{
if (hFile.name[0] != '.') // 文件名不是'.'或'..'时
{
memset(szPath, 0, sizeof(szPath));
_snprintf(szPath, sizeof(szPath)-1,"%s\\%s", pPath, hFile.name);
printf("检查目录: %s\n", szPath);
Check(szPath); // 继续遍历
Sleep(10);
}
}
else // 如果第一个实体不是目录,显示该文件
{
// 再获得文件的完整的路径名(包含文件的名称)
memset(szPath,0, sizeof(szPath));
_snprintf(szPath, sizeof(szPath)-1,"%s\\%s", pPath, hFile.name);
ModifyFileName(pPath, hFile.name);
}
// 继续对当前目录中的下一个子目录或文件进行与上面同样的查找
while (!(_findnext(handle, &hFile)))
{
if (hFile.attrib &_A_SUBDIR ) // 是目录
{
if (hFile.name[0] != '.') // 文件名不是'.'或'..'时
{
memset(szPath, 0, sizeof(szPath));
_snprintf(szPath,sizeof(szPath)-1, "%s\\%s", pPath, hFile.name);
printf("检查目录: %s\n", szPath);
Check(szPath); // 继续遍历
Sleep(10);
}
}
else //如果第一个实体不是目录,显示该文件
{
memset(szPath, 0, sizeof(szPath));
_snprintf(szPath, sizeof(szPath)-1,"%s\\%s", pPath, hFile.name);
ModifyFileName(pPath, hFile.name);
}
}
_findclose(handle);
}
}
/****************************************************************
* 功能描述: 主函数
* 输入参数: argc-输入的整型入参
argv-输入的字符型入参
* 输出参数: 无
* 返回值: 0-执行成功 -1-执行失败
* 其它说明:无
* 修改日期 版本号 修改人 修改内容
*--------------------------------------------------------------
* 20141117 V1.0 zzx 新建
****************************************************************/
int main(int argc, char*argv[])
{
char szPathName[1000] = {0};
int iPathLen = 0;
int iRetVal = 0;
printf("starting...\n");
// 先读取全局配置
iRetVal = GetAppConfig();
if (iRetVal != 0)
{
return -1;
}
if (4 != argc)
{
printf("argc=%d\n", argc);
printf("用法: touch.exe 目录名保持天数是否恢复\n例1: touch.exe D:\\work 60 1\n例2: touch.exe \"D:\\w o rk\" 60 0\n");
return -1;
}
else
{
char szTempPath[1000] = {0};
//目录名称
strncpy(szTempPath, argv[1], sizeof(szTempPath)-1);
iPathLen = strlen(szTempPath);
if (iPathLen = 'A') &&(szTempPath[0] = 'a') &&(szTempPath[0]
2. 修改后缀的过程
step 1:
在本地的D盘中,有一个叫做“Test”的文件夹,该文件夹下有一个命名为“123.doc”的文件,如下图所示:
在任一文件夹下新建两个文件夹,分别命名为“Old2New”(表示旧的后缀修改为新的后缀)和“New2Old” (表示新的后缀修改为旧的后缀),并将C程序运行生成的“ChangeSuffix.exe”拷贝到两个文件夹下。
step 2:
在这两个文件夹下新建名为“Config.ini”的配置文件,该文件中的各个配置项如下:
[General]
; 将老的后缀转换为新的后缀,或是将新的后缀转换为老的后缀,1--Old -> New, 2--New -> Old
Old2NewOrNew2Old =
; 旧的文件后缀(支持配置多个, 中间有;隔开)
OldSuffix = doc;xls;ppt
; 新的文件后缀(支持配置多个, 中间有;隔开)
NewSuffix = docx;xlsx;pptx
其中,“Old2New”文件夹下的“Old2NewOrNew2Old”设置为1,“New2Old”文件夹下的“Old2NewOrNew2Old”设置为2,其它配置项保持一致。
step 3:
在“Old2New”文件夹下新建名为“update.bat”的批处理文件,该文件的内容为:
ChangeSuffix "D:\\Test" 60 0
其中,“D:\\Test”为待修改后缀的文件的存放路径。
在“New2Old”文件夹下新建名为“update_restore.bat”的批处理文件,该文件的内容为:
ChangeSuffix "D:\\Test" 60 1
其中,“D:\\Test”为待修改后缀的文件的存放路径。
“Old2New”和“New2Old”两个文件夹下的文件存放情况如下:
step 4:
分别双击“update.bat”和“update_restore.bat”,即可实现旧新和新旧后缀的转换功能。
(本人微博:http://weibo.com/zhouzxi?topnav=1&wvr=5,微信号:245924426,欢迎关注!)