MFC中CStdioFile处理文本文件乱码的
参考
MFC中CStdioFile处理文本文件乱码的原因及解决方法(编程 Unicode 环境下读写 ANSI 文件)http://hi.baidu.com/jfc_09/blog/item/f4d7fdd72685a8cf50da4b79.html
VC 编程ANSI环境下读写Unicode文件
http://blog.csdn.net/sunboy_2050/archive/2009/12/17/5019900.aspx-->
CStdioFile在UNICODE环境下读取文本行〔转〕 - 乖小猫的日志 - 网易博
!!!http://blog.163.com/neverforget_yang/blog/static/13095275720104482459666/
BOOL CLanguageManager::ParseResourceFile(LPCTSTR lpszFilePath, LPCTSTR lpszHeaderFilePath) {.. // resource file CStdioFile Resfile; if (Resfile.Open(lpszFilePath, CFile::modeRead)) { int index =0; CString src; CString strHeaderRow; while (Resfile.ReadString(strHeaderRow)) { !!!Ansi2Unicode(strHeaderRow); src = src + _T("\r\n"); src = src + strHeaderRow; }
// 将Unicode字符转换为Char型字符 #define BUFFER_SIZE_KILO 0 int UnicodeToChar(CString &strIn, char *pchOut, int nCharLen) { if(pchOut == NULL) { return 0; } int nLen = WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)strIn.GetBuffer(BUFFER_SIZE_KILO),-1, NULL, 0, NULL, NULL); nLen = min(nLen, nCharLen); WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)strIn.GetBuffer(BUFFER_SIZE_KILO), -1, pchOut, nLen, NULL, NULL); if(nLen < nCharLen) { pchOut[nLen] = 0; } return nLen; } void Ansi2Unicode(CString &str) { //注:此函数在编译的时候会提示 // warning C4244: '=' : conversion from 'unsigned short' to 'char', possible loss of data // 不用管它,丢失的数据是我们不需要的。 char *szBuf = new char[str.GetLength()]; for (int i = 0 ; i < str.GetLength(); i++) { szBuf[i] = str.GetAt(i); } CharToUnicode(szBuf , &str); delete []szBuf;
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
CStdioFile Resfile; if (Resfile.Open(lpszFilePath, CFile::modeRead)) { int index =0; CString src; CString str_Unicode,str_MSBC; while (Resfile.ReadString(str_MSBC)) { // 注意:采用这种方式处理的文件必须为ANSI编码,不能使UNICODE // 把“_MSBC环境”下的“CString”(CHAR),直接填充到了“Unicode环境”下的“CString”(WCHAR)中, // 这样会导致“汉字”显示成乱码。如果想正确显示,需要对该字符串进行相应的处理。 if(str_MSBC != _T("")) { // 将保存成“宽字节类型”的“单字节类型”字符串(Unicode环境), // 还原为正确的“单字节类型”字符串(_MSBC环境)。 _UnicodeOf_MSBCTo_MSBC(&str_MSBC); // 将“单字节的字串符类型(_MSBC环境)”转换为“宽字节的字符串类型(Unicode环境)” _MSBCTo_Unicode(str_MSBC, &str_Unicode);
}
上述处理有问题,后来又参照 http://hi.baidu.com/coderui/item/a9a634439e25ca15896d108d
进行处理
CStdioFile Resfile; if (Resfile.Open(lpszFilePath, CFile::modeRead)) { int index =0; CString src; CString str_Unicode,str_MSBC; while (Resfile.ReadString(str_MSBC)) { // 注意:采用这种方式处理的文件必须为ANSI编码,不能使UNICODE // 把“_MSBC环境”下的“CString”(CHAR),直接填充到了“Unicode环境”下的“CString”(WCHAR)中, // 这样会导致“汉字”显示成乱码。如果想正确显示,需要对该字符串进行相应的处理。 if(str_MSBC != _T("")) { // 将保存成“宽字节类型”的“单字节类型”字符串(Unicode环境), // 还原为正确的“单字节类型”字符串(_MSBC环境)。 _UnicodeOf_MSBCTo_MSBC(&str_MSBC); // 将“单字节的字串符类型(_MSBC环境)”转换为“宽字节的字符串类型(Unicode环境)” _MSBCTo_Unicode(str_MSBC, &str_Unicode);
// // 将“单字节的字串符类型(_MSBC环境)”转换为“宽字节的字符串类型(Unicode环境)” // INT _MSBCTo_Unicode(CString strInPut_MSBC, CString *strOutPut_Unicode) { INT nLen; CHAR *pcBuf; if(strInPut_MSBC == _T("")) { return 0; } pcBuf = (CHAR *)strInPut_MSBC.GetBuffer(strInPut_MSBC.GetLength()); nLen = MultiByteToWideChar(CP_ACP, 0, pcBuf, -1, NULL, 0); // (Unicode环境WCHAR需要加1,默认已经加1了) WCHAR *pwBuf = new WCHAR[nLen]; memset(pwBuf, 0, nLen); MultiByteToWideChar(CP_ACP, 0, pcBuf, -1, pwBuf, nLen); strOutPut_Unicode->Format(_T("%s"), pwBuf); delete []pwBuf; nLen -= 1; return nLen; } // // 将“宽字节的字符串类型(Unicode环境)”转换为“单字节的字串符类型(_MSBC环境)” // INT _UnicodeTo_MSBC(CString strInPut_Unicode, CString *strOutPut_MSBC) { INT nLen; WCHAR *pwBuf; if(strInPut_Unicode == _T("")) { return 0; } pwBuf = strInPut_Unicode.GetBuffer(strInPut_Unicode.GetLength()); nLen = WideCharToMultiByte(CP_ACP, 0, pwBuf, -1, NULL, 0, NULL, NULL); // (Unicode环境需要加2,不然Format时内存数据格式不对程序会崩) CHAR *pcBuf = new CHAR[nLen + 2]; memset(pcBuf, 0, nLen + 2); WideCharToMultiByte(CP_ACP, 0, pwBuf, -1, pcBuf, nLen, NULL, NULL); strOutPut_MSBC->Format(_T("%s"), pcBuf); delete []pcBuf; nLen -= 1; return nLen; } // // 将保存成“宽字节类型”的“单字节类型”字符串(Unicode环境), // 还原为正确的“单字节类型”字符串(_MSBC环境)。 // VOID _UnicodeOf_MSBCTo_MSBC(CString *str) { INT nLen; CHAR *pcBuf; nLen = str->GetLength(); // (Unicode环境需要加3,不然Format时内存数据格式不对程序会崩) pcBuf = new CHAR[nLen + 3]; memset(pcBuf, 0, nLen + 3); for (INT i = 0 ; i < nLen; i++) { pcBuf[i] = (CHAR)str->GetAt(i); } str->Format(_T("%s"), pcBuf); delete []pcBuf; }