我有一个 MFC 项目,它从 ANSI 文件读取和写入。应用程序的字符集设置为Unicode。
附录
我无法更改/影响输入和输出文件的编码,因为在我的上下文中,我们谈论的是旧软件之间的转换器。预期的字符编码实际上是windows-1252。
在读写一些文件时,我注意到一些很少使用的字符,比如在Š (0x8A)
用. 我创建了一个测试文件来查看在和之间的范围内哪些字符受到影响。? (0x3F)
CStdioFile
0x30
0xFF
我将这些字符复制到一个测试文件(ANSI 编码)(从 0x30 到 0xFF 的字符)
结果文件如下所示:
更改的字符都在同一区域周围,并且都更改为0x3F '?'
- 从0x80
up to开始0x9F
。奇怪的是,有一些例外,如0x81
, 0x8D
,0x90
并且0x9D
没有受到影响。
测试行为的示例代码:
//prepare vars
CFileException fileException;
CStdioFile filei;
CStdioFile fileo;
CString strText;
//open input file
filei.Open(TEXT("test.txt"), CFile::modeRead | CFile::shareExclusive | CFile::typeText, &fileException);
//open output file
fileo.Open(TEXT("testout.txt"), CFile::modeCreate | CFile::modeWrite | CFile::shareExclusive | CFile::typeText, &fileException);
//read and write
BOOL eof = filei.ReadString(strText) <= 0;
fileo.Write(CStringA(strText), CStringA(strText).GetLength());
//clean up
filei.Close();
fileo.Close();
为什么要这样做,我需要做些什么来保留所有字符?
禁用 unicode 模式可以解决问题,但不幸的是,在我的情况下不是一个选项。
总结
这是从接受的答案中摘录的对我有用的东西:
不要通过调用它的构造函数CStringW
来转换。CStringA
从 Unicode 转换为 "ANSI" (Windows1252) 时,请使用CW2A
:
CStringA strTextA(strText, CP_ACP)` //CP_ACP converts to ANSI
fileo.Write(strTextA, strTextA.GetLength());
更简单:使用CStdioFile::WriteString
方法而不是CStdioFile::WriteS
:
fileo.Open(TEXT("testout.txt"), CFile::modeCreate | CFile::modeWrite | CFile::shareExclusive | CFile::typeText, &fileException);
fileo.WriteString(strText);