描述:
源文件是按unicode编码的文本文件有这样一段
[应用版本号] "1.0.0"
主题名称] "202"
[主题图标路径] "themeIcons//202.gif"
........
根据传进来的参数,比如是vmax就要修改成
[应用版本号] "1.0.0"
主题名称] "vmax"
[主题图标路径] "themeIcons//vmax.gif"
.......
我用的是vc,字符集采用的是“多字节字符集”
首先以二进制方式打开文件,这里面说一下二进制方式和文本方式有什么不同
这些不同主要是在一些API上,某些API会根据打开方式的不同对文件中的“回车换行”符(/r/n)做特殊处理。注意这是两个字符,在ascii下由0d和0a表示。
查阅msdn 在cstdiofile下面有这样一段remarks
Stream files are buffered and can be opened in either text mode (the default) or binary mode.
Text mode provides special processing for carriage return–linefeed pairs. When you write a newline character (0x0A) to a text-mode CStdioFile object, the byte pair (0x0D, 0x0A) is sent to the file. When you read, the byte pair (0x0D, 0x0A) is translated to a single 0x0A byte.
是说当使用writestring是字符串末尾的'/0'不会被写到文件中,以文本方式打开其中的换行符'/n'ascii表示是0a都会被转换成"/r/n"ascii表示是0x0d0x0a 。
以二进制方式打开的文件不会出现这种转换。
接下来就说说怎么样在多字节字符集下去修改Unicode文件
修改文件一般用覆盖的方式。根据要修改的内容和原有内容长度的不同(按字节算)有三种情况(假设pos是你要修改的位置):
1,和原来的一样长,在pos处直接写覆盖就可以了。
2,比原来的长n字节,自pos的所有内容后移n个字节后,再从pos写入 以刚好凑成等长
3,比原来的短n字节,自pos+n后的所有内容n个字节,再从pos写入,最后还要将文件末尾的n个字节删除.可以用setlength方法
下面展出一段示例代码:
自posb开始文件内容后移off个字节的方法最简单的:
求剩余字节:int len = file.GetLength() - posb;
然后读取剩余字节:
char* buff = new char[len];
file.Seek(posb, CFile::begin);
int res = file.Read(buff, len);
接着从posb+off写入剩余内容
file.Seek(posb + off, CFile::begin);
file.Write(buff, res);
file.Flush();
接着把我们要添加的内容从posb写入
file.Seek(posb, CFile::begin);
file.WriteString(comment);
以上是修改的过程,下面要实现cstdiofileex类,实现writestring和readstring。以便从unicode文件中用readstring方法读一行Mutibyte编码的字符串。并且用writestring将mutibyte字符串以unicode编码写道文件
列出这两个函数
cstdiofileex的源文件转自http://blog.youkuaiyun.com/Augusdi/archive/2009/10/15/4677520.aspx
我针对自己的应用做了些修改
特别要注意其中的一段
wchar_t* p = pszUnicodeString;
while(*p){
CFile::Write(p, 2);
p++;
}
//CFile::Write(pszUnicodeString, lstrlen(lpsz) * sizeof(wchar_t));
作者原来使用的是注释行CFile::Write(pszUnicodeString, lstrlen(lpsz) * sizeof(wchar_t));
这里有一点小失误因为他用int nChars = lstrlen(lpsz); 获取字符个数,这在mutibyte下是不合适的。汉字本身已经占了2字节
如果原文中有汉字,在用CFile::Write(pszUnicodeString, lstrlen(lpsz) * sizeof(wchar_t));是就会把结尾处几个多余的空字节写到文件中。读者可以自己传带汉字的字符串做个小实验。
所以我每次只写入两个字节遇到0x000x00时结束,这样做的坏处是会重复的发出I/O请求,耗费大量资源。有一个比较好的方法是用
_mbslen代替lstrlen这个函数可以返回mutibyte字符的个数。详见msdn
就写这么多了 因为基本不用mfc 最近要开发一个小工具 才练练。 代码纰漏之处请见谅。