替换文件中的字符串(C语言实现)
2013-12-15 20:18
288 查看
最近项目中需要一个小功能:读入一个文本文件,将其中的字符串A全部替换为字符串B。我接到任务后马上动手实现了一个:(MFC)
1. 读入文本 CStdFile
2. 逐行读入文本 CStdFile::ReadString
3. 查找字符串A,删除字符串A,插入字符串B CString
4. 全部完成,写入文件
结果在使用时,老是会出现乱码,检查代码页发现没有问题;调试发现,缓冲区的数据居然是乱码的。我意识到,可能是字符编码的问题,于是把工程设置成Unicode(vs2008),问题依然存在。用npp看了下文件的编码,发现是UTF8,在网上谷歌了个格式的转换的代码,搞定!可是后来又出现了问题,打开一看,这次的文件编码又是ASCII的了…
难道我在每次转换之前要先判断一下文件的编码格式,然后转换成统一的编码?我发现这样我还要再写Unicode转ASCII,UTF8转ACSII…一系列函数,这个方案可行,但是很费力;但不这样做,怎样用同一种方案解决所有编码的问题呢?其实问题很简单,不管文件的编码是怎样的,它在计算机中表现出来的形式都是统一的,都是一个个字节的数据,以这样的方式来看,问题的本质也就是替换字符串A的字节表示为字符串B的字节表示;
代码中关于错误处理还不完善,如有需要,请自行添加;
1. 读入文本 CStdFile
2. 逐行读入文本 CStdFile::ReadString
3. 查找字符串A,删除字符串A,插入字符串B CString
4. 全部完成,写入文件
结果在使用时,老是会出现乱码,检查代码页发现没有问题;调试发现,缓冲区的数据居然是乱码的。我意识到,可能是字符编码的问题,于是把工程设置成Unicode(vs2008),问题依然存在。用npp看了下文件的编码,发现是UTF8,在网上谷歌了个格式的转换的代码,搞定!可是后来又出现了问题,打开一看,这次的文件编码又是ASCII的了…
难道我在每次转换之前要先判断一下文件的编码格式,然后转换成统一的编码?我发现这样我还要再写Unicode转ASCII,UTF8转ACSII…一系列函数,这个方案可行,但是很费力;但不这样做,怎样用同一种方案解决所有编码的问题呢?其实问题很简单,不管文件的编码是怎样的,它在计算机中表现出来的形式都是统一的,都是一个个字节的数据,以这样的方式来看,问题的本质也就是替换字符串A的字节表示为字符串B的字节表示;
bool ReplaceFileContent( char * fileName, const char *oldStr, const char *newStr ) { CFile file; unsigned int oldStrSize; unsigned int newStrSize; const unsigned char *pOldStr; const unsigned char *pNewStr; unsigned char *pFileData = NULL; unsigned int fileSize; unsigned int bufSize; unsigned int filePos; file.Open( fileName, CFile::modeReadWrite | CFile::typeBinary , NULL ); fileSize = (unsigned int)file.GetLength( ); bufSize = fileSize * 2; pFileData = (unsigned char *) malloc( bufSize * sizeof( unsigned char) ); // 先分配两倍数据大小的内存,因为字符串长度可能不同,避免频繁realloc if ( !pFileData ) { return false; } file.Read( pFileData, fileSize ); pOldStr = (const unsigned char *)oldStr; pNewStr = (const unsigned char *)newStr; for ( oldStrSize = 0; oldStr[oldStrSize]; oldStrSize++ ) ; for ( newStrSize = 0; newStr[newStrSize]; newStrSize++ ) ; for ( filePos = 0; filePos < fileSize; ) { unsigned int oldPos; for ( oldPos = 0; oldPos < oldStrSize; ) /* 查找字符串 */ { if ( pFileData[filePos + oldPos] == pOldStr[oldPos] ) { oldPos++; continue; } else { break; } } if ( oldPos >= oldStrSize ) /* 发现匹配 */ { if ( newStrSize == oldStrSize ) { for ( unsigned int index = 0; index < oldStrSize; index++ ) { pFileData[filePos++] = pNewStr[index]; } } else if ( newStrSize < oldStrSize ) { unsigned int index; unsigned int adjustment; adjustment = oldStrSize - newStrSize; for ( index = 0; index < newStrSize; index++ ) { pFileData[filePos++] = pNewStr[index]; } for ( unsigned int headPtr = filePos; headPtr < fileSize; headPtr++) /* 调整位置 */ { pFileData[headPtr] = pFileData[headPtr + adjustment]; } fileSize = fileSize - adjustment; } else if ( newStrSize > oldStrSize ) { unsigned int adjustment; unsigned int tailPtr; /* 指向文件尾部 */ adjustment = newStrSize - oldStrSize; fileSize = fileSize + adjustment; if ( fileSize > bufSize ) { void *pStretch = realloc( pFileData, fileSize + adjustment ); /* 扩大数据区 */ if ( !pStretch ) // 防止分配失败丢失原来的数据 { return false; } pFileData = (unsigned char *) pStretch; } for ( tailPtr = fileSize; tailPtr > filePos + oldStrSize - 1; tailPtr--) { pFileData[tailPtr] = pFileData[tailPtr - adjustment]; } for ( unsigned int index = 0; index < newStrSize; index++ ) { pFileData[filePos++] = pNewStr[index]; } } } else { filePos++; } } CFile newFile( fileName, CFile::modeCreate | CFile::modeWrite | CFile::typeBinary ); // modeCreate必须,清空文件重写 newFile.Write( pFileData, fileSize); newFile.Close( ); file.Close( ); free( pFileData ); return true; }
代码中关于错误处理还不完善,如有需要,请自行添加;
相关文章推荐
- 替换文件中某个字符串并写入新内容(Java代码实现)
- sed find grep协同作战,实现多文件字符串替换
- C语言实现文件字符替换
- C语言实现文件字符替换
- C语言实现字符串替换
- C语言字符串替换函数,字符串插入函数的实现
- Python实现多个文件中替换字符串
- 【C语言】【面试题】【笔试题】.字符串替换空格:请实现一个函数,把字符串中的每个空格替换成“%20”。
- 替换文件中某个字符串并写入新内容(Java代码实现)
- C语言实现#include替换文件
- C语言现代方法之实现字符串的替换
- 使用wxString实现字符串在一个文件里面的替换
- C语言实现:替换字符串中指定字符
- 替换文件中某个字符串并写入新内容(Java代码实现)
- 使用C语言实现字符串中子字符串的替换
- Java实现--替换文本文件中所有符合条件的字符串
- 【c语言】字符串替换空格:请实现一个函数,把字符串中的每个空格替换成“%20”
- C语言现代方法之实现字符串的替换
- 【C语言】字符串替换空格:实现一个函数,把字符串里的空格替换成“%20”
- C语言实现读取文件所有内容到字符串