您的位置:首页 > 编程语言 > C语言/C++

替换文件中的字符串(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的字节表示;

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


代码中关于错误处理还不完善,如有需要,请自行添加;
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: