急!崩溃!vc2005 向txt文件写入UNICODE字符乱码!

vcminusminus 2009-12-07 12:47:37
加精
环境:WIN2003SP2 + VC2005(补丁版本SP.050727-7600)

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

日志文件变量为CStdioFile类型。日志字符串变量为CString类型,将每步操作情况为一行,使用“\r\n”分行,最后将该字符串写到日志文件中
在VC6中的关键代码如下:
//VC6
CStdioFile 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()宏处理了一下字符串常量):
//VC2005,UNICODE
CStdioFile 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的相关文件操作,同样写入后乱码。关键代码为:
#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);



被这个问题缠了一上午了,已经焦头烂额,非常紧急!请朋友们帮忙!
...全文
5698 176 打赏 收藏 转发到动态 举报
写回复
用AI写文章
176 条回复
切换为时间正序
请发表友善的回复…
发表回复
xiaoniaozhubo 2012-02-24
  • 打赏
  • 举报
回复
这个Bug是怎么解决的呢?
[Quote=引用 98 楼 liuxiaoyi666 的回复:]
引用 24 楼 vcminusminus 的回复:
to akirya:
是呀,这个我试过了,的确不乱码,但是不行啊,w模式是覆盖,而不是追加,我的项目要求日志内容必须是连续追加的。

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

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


....貌似又受到了不知名的……
[/Quote]
andywa 2012-01-04
  • 打赏
  • 举报
回复
能不能回复了,我也遇到这个问题了,用file.Write("\r\n",2)行,打开一看,还是个“口”,
后来直接这样子写了:
unsigned int row = 0x000d;
unsigned int enter = 0x000a;

file.Write(&row,2);
file.Wirte(&enter,2);

然后就没有乱码了。
public 2011-07-28
  • 打赏
  • 举报
回复
mark
jasmine 2011-04-24
  • 打赏
  • 举报
回复
各位高人
路过此地
虽然不懂
但是 也想凑个热闹
秦剑 2010-12-01
  • 打赏
  • 举报
回复
中文够烦人 以前遇到过 不过没有用CStdioFile
先查查CStdioFile 的机制试试
liuxianliuxian 2010-09-20
  • 打赏
  • 举报
回复
不好意思错了,还要设成:CFile::typeBinary
这样就可以了
liuxianliuxian 2010-09-20
  • 打赏
  • 举报
回复
#include <locale>//头文件
setlocale( LC_CTYPE, "chs" )

这个貌似也没用啊
vcminusminus 2009-12-30
  • 打赏
  • 举报
回复
感谢大家的帮助和参与!这个帖子就到此为止吧,以后我总结的时候再新开一个!
dadahacker 2009-12-16
  • 打赏
  • 举报
回复
都不明白怎么回事,希望出点精华。
xiaowen_ly 2009-12-11
  • 打赏
  • 举报
回复
这个问题我碰见过,改成utf后就显示正确了
天高云淡 2009-12-11
  • 打赏
  • 举报
回复
UNICODE编码写入文件前要在文件开头处加标志"FEFF",可以使用UltraEdit查看一UNICODE编码文件验证。

下面代码中m_fileLog是CFile类型,开发环境如果是UNICODE,则条件编译有效。
条件编译中的代码是用来判断如果文件是新建的则在文件头写入“FEFF”标志。
#ifdef UNICODE
if(0==m_fileLog.GetLength())
{
wchar_t cBOM = 0xFEFF;
m_fileLog.Write(&cBOM,sizeof(wchar_t));
}
#endif

CString strLog(_T("abcdefg"));
m_fileLog.SeekToEnd();
m_fileLog.Write(strLog,strLog.GetLength()*sizeof(TCHAR));
shiwei0124 2009-12-11
  • 打赏
  • 举报
回复
mark
何日人再来 2009-12-11
  • 打赏
  • 举报
回复
收藏
wishfly 2009-12-10
  • 打赏
  • 举报
回复
mark
winnuke 2009-12-10
  • 打赏
  • 举报
回复
哎,插个嘴。
采用unicode字符集的时候,数据在传输需要一个特定的编码方案。于是出了一系列叫utf(ucs tranform format)的编码方案。其中主要分为定长和不定长两种方案。前者相对而言就是采用ucs2,ucs4固定字节来表示unicode的第一个平面(bmp)的16位比特。而后者典型的代表是utf8编码,这个方案在表示英文的时候特别节省空间,表示东亚字符的时候每个字符至少需要3个字节。而ucs2是以2字节为单位的编码单元,在不同机器上表示形式可能会不同,于是又分为bigendian和littleendian,因为0xff 0xfe在utf8里是没有使用的,所以标准里规定了传输的时候先传输这两个字节表示是unicode的固定编码,且两者先后顺序不同也代表着不同的字节顺序。
windows上的记事本也是采用了这一方案,0xff0xfe表示的是littleendian 0xfe0xff表示的是bigendian。windows上默认的是littleendian,而标准中默认规定unicode为littleendian。
糖炒栗子 2009-12-10
  • 打赏
  • 举报
回复
个人建议中文最好是UTF8.

例子见log4cplus等等...
a449276231 2009-12-10
  • 打赏
  • 举报
回复
大家好,我是新成员,请多多关照
jcjunjin 2009-12-10
  • 打赏
  • 举报
回复
学习中
hdqqq 2009-12-10
  • 打赏
  • 举报
回复
UINICODE 文件需要一个bom头,在写文件前写两个字节 FF FE,这样notepad可以正确识别.
pli0825 2009-12-10
  • 打赏
  • 举报
回复
dddddddddddd。
加载更多回复(152)

16,472

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Web++
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧