读书人

急崩溃!vc2005 向txt文件写入UNICODE

发布时间: 2012-01-19 20:57:58 作者: rapoo

急!崩溃!vc2005 向txt文件写入UNICODE字符乱码!
环境:WIN2003SP2 + VC2005(补丁版本SP.050727-7600)

一个操作日志程序,每个操作完成后既在窗口的监视编辑框中显示操作情况,又要将其写入到日志文本文件中。
这个项目以前是在VC6下做的,没有使用UNICODE,写入日志文件后用记事本读取时没有问题,不会乱码。
现在把这个项目升级到VC2005并且使用UNICODE,导致用记事本打开日志文件时除了数字和英文外,其余均乱码。

日志文件变量为CStdioFile类型。日志字符串变量为CString类型,将每步操作情况为一行,使用“\r\n”分行,最后将该字符串写到日志文件中
在VC6中的关键代码如下:

C/C++ code
//VC6CStdioFile m_LogFile;//日志文件对象CString m_strLog;//日志内容字符串CString m_strLogFileName("DownLoad");//日志文件名称CFileException fe;//文件异常对象if(!m_LogFile.Open(m_strLogFileName   ,CFile::modeCreate|CFile::modeNoTruncate|CFile::modeReadWrite|CFile::shareDenyNone|CFile::typeText   ,&fe)){    char szErro[300] = {0};    fe.GetErrorMessage(szErro,300,NULL);    CString strMessage;    strMessage.Format("打开日志文件%s失败,无法记录操作过程!\r\n错误信息为:%s"        ,m_strLogFileName,szErro);    ::MessageBox(NULL,strMessage,"无法打开日志文件",MB_OK);    return FALSE;}//开始记录m_strLog += "开始操作...\r\n";m_strLog += "操作一情况...\r\n";m_strLog += "操作二情况...\r\n";/*省略。。。*///写入日志文件m_LogFile.SeekToEnd();m_LogFile.WriteString(m_strLog + "\r\n");        m_LogFile.Flush();


在VC2005中对应的代码如下(仅是使用_T()宏处理了一下字符串常量):
C/C++ code
//VC2005,UNICODECStdioFile m_LogFile;//日志文件对象CString m_strLog;//日志内容字符串CString m_strLogFileName(_T("DownLoad"));//日志文件名称CFileException fe;//文件异常对象if(!m_LogFile.Open(m_strLogFileName   ,CFile::modeCreate|CFile::modeNoTruncate|CFile::modeReadWrite|CFile::shareDenyNone|CFile::typeText   ,&fe)){    TCHAR szErro[300] = {0};    fe.GetErrorMessage(szErro,300,NULL);    CString strMessage;    strMessage.Format(_T("打开日志文件%s失败,无法记录操作过程!\r\n错误信息为:%s")        ,m_strLogFileName,szErro);    ::MessageBox(NULL,strMessage,_T("无法打开日志文件"),MB_OK);    return FALSE;}//开始记录m_strLog += _T("开始操作...\r\n");m_strLog += _T("操作一情况...\r\n");m_strLog += _T("操作二情况...\r\n");/*省略。。。*///写入日志文件m_LogFile.SeekToEnd();m_LogFile.WriteString(m_strLog + _T("\r\n"));        m_LogFile.Flush();



另外,还尝试了C的相关文件操作,同样写入后乱码。关键代码为:
C/C++ code
#include <stdio.h>//打开日志文件(注意:去掉ccs=UNICODE也同样乱码!)FILE *pfile = _wfopen(L"DownLoad.log",L"at,ccs=UNICODE");//at:a表示追加,t表示文本方式//记录日志CString strLog(_T("操作开始...\r\n"));strLog += _T("操作一...\r\n");/*省略....*///将日志写入文本文件fwrite(strLog.GetBuffer(),sizeof(strLog.GetAt(0)),strLog.GetLength(),pfile);strLog.ReleaseBuffer();fflush(pfile);



被这个问题缠了一上午了,已经焦头烂额,非常紧急!请朋友们帮忙!

[解决办法]
CStdioFile类,在Unicode下确实会出现这样的问题...
WriteString之前添加以下代码

C/C++ code
        unsigned short int feff=0xfeff;           m_LogFile.Write(&feff,sizeof(short int));
[解决办法]
在日志文件头部写入0xfeff,以后就不要再写了,"\r\n"跟乱码没有关系。

探讨
引用:
CStdioFile类,在Unicode下确实会出现这样的问题...
WriteString之前添加以下代码

C/C++ code        unsignedshortint feff=0xfeff;
        m_LogFile.Write(&feff,sizeof(shortint));




--------------------------
谢谢书记与众不同的方法!
按照您的方法,每次写入的日志中只有第一个\r\n前的字符串不是乱码,其余的都是乱码(直到下一次写入之前),并且不分行乐了。
即使在写入文件前使用了
C/C++ codem_strLog.Replace(_T("\r\n"),_T("\n"));
也一样。

[解决办法]
按二进制方式读写文件,如果存储为utf16-little endian格式,就是windows下面常规的unicode格式,需要在文件最前面写上0xff, 0xfe,这样记事本就认正确了。

[解决办法]

探讨
to akirya:
    是呀,这个我试过了,的确不乱码,但是不行啊,w模式是覆盖,而不是追加,我的项目要求日志内容必须是连续追加的。

to M_S_D_N:
  typeBinary也试过了,依然乱码。

不管怎样,还是要谢谢你们的热心帮忙,你们比那些沾满铜臭的所谓MVP们强多了!!!

[解决办法]
探讨
to akirya:
    是呀,这个我试过了,的确不乱码,但是不行啊,w模式是覆盖,而不是追加,我的项目要求日志内容必须是连续追加的。

to M_S_D_N:
  typeBinary也试过了,依然乱码。

不管怎样,还是要谢谢你们的热心帮忙,你们比那些沾满铜臭的所谓MVP们强多了!!!

读书人网 >VC/MFC

热点推荐