首页 新闻 会员 周边 捐助

C++ 中文显示??

0
[已解决问题] 解决于 2012-12-24 14:09

开发平台:Win7 32bit 英文版
开发工具:VS2008 英文版
开发语言:C++
程序编码:ANSI(MBCS)
运行平台:Win2003 英文版;Regional and Language Options—Advanced标签里面选择 Chinese(PRC);Language标签里面勾选Install files for East Asian languages,但是灰色不可 更改。


问题描述:C++程序抓取某系统值(中文的),输出到本地log文件,中文显示???。但是该程序在别的机器上没有发现该问题。而且该机器上能显示或者输入中文字,中文版本的软件也能安装,没有显示乱码。

为什么。。。

杨彬Allen的主页 杨彬Allen | 菜鸟二级 | 园豆:261
提问于:2012-12-20 15:03
< >
分享
最佳答案
0

首先你得判断抓取到的字符串是否是正确的中文,

其次在输出文件的时候,你可以采用支持中文字符的字符集(不要选 GB2312,很可能 OS 没有) Unicode或UTF-8之类的来输出你的log文件。

奖励园豆:5
Launcher | 高人七级 |园豆:45050 | 2012-12-20 15:42

您好,多谢回复!!

1. 怎么判断是否是正确的中文?我是抓取打印机里面的作业名,比如打印一个中文文档,别的机器我打印同一个文档能成功抓取到中文并输出。

2. 文件我输入到txt的,使用log4cplus。感觉和什么编码写文件无法,因为我把这个字串转成UTF-8再输出也是乱码。

3. 是否程序中都用使用unicode编码?

杨彬Allen | 园豆:261 (菜鸟二级) | 2012-12-20 16:40

@楊彬: 1,把抓取到的文字显示到你的UI上,就能看出来是否正确。

2,我不知道log4cplus是怎么处理中文的,我只说一个关于如何在非中文操作系统下正确读写INI的例子,我假设项目字符集是UNICODE,同时项目中使用LPCTSTR来表示字符串,并且假设此字符串中的中文字符是正确的,如下:

LPCTSTR lpszText = _T("中文"); // 由于是写在代码中的,那么lpszText肯定包含正确的中文字符。

现在要写入INI文件,由于默认的API创建的INI文件在非中文操作系统下无法正确对中文字符编码,所以我在调用 WritePrivateProfileString 之前,先手动创建一个正确的 INI 文件,如下:

        HRESULT hr = ::SHPathPrepareForWrite(NULL,NULL,lpszINIFileName,SHPPFW_DIRCREATE | SHPPFW_IGNOREFILENAME);
        if(hr != S_OK) return hr;

        // INI 能够正确识别的 UNICODE 字符集为 UTF16-little Endian,
        // 但是由 WritePrivateProfileString 自动创建的文件是 ANSI 编码,
        // 所以我们通过编码方式创建带有正确 BOM 信息并能够识别中文
        // 字符的 INI 文件。
        // UTF16-LE BOM(FFFE)
        WORD wBOM = 0xFEFF;
        DWORD dwWritten;

        TCHAR szComment[MAX_PATH] = 
            _T(";**********************************************************\r\n")
            _T(";此 INI 文件由程序自动创建,采用 UTF16-little Endian 编码,\r\n")
            _T(";文件头包含 2 个字节的编码标识(0xFEFF),可在非中文操作系\r\n")
            _T(";统下正确读、写中文字符。禁止修改文件头!\r\n")
            _T(";**********************************************************\r\n\r\n");

        HANDLE hFile = ::CreateFile(
            lpszINIFileName,
            GENERIC_WRITE,
            FILE_SHARE_READ,
            NULL,
            CREATE_ALWAYS,
            FILE_ATTRIBUTE_NORMAL,
            NULL);

        if (hFile == INVALID_HANDLE_VALUE)
            return ::AtlHresultFromLastError();

        ::WriteFile(hFile, &wBOM, sizeof(WORD),&dwWritten, NULL);
        ::WriteFile(hFile, szComment, (_tcslen(szComment)+1)*(sizeof(TCHAR)),&dwWritten, NULL);

        ::CloseHandle(hFile);

那么此后我再使用这个已经存在的文件,调用 WritePrivateProfileString 写入 lpszText 后,通过记事本,或者使用 GetPrivateProfileString ,你就能看到或得到正确的中文字符。

3,推荐设置为 UNICODE 编码,会减少很多转码的问题。

请仔细读一下 log4cplus 的源码,看看它创建文件的方式,以及它写入字符串的类型。比如ZLIB,它的所有方法都使用 char 来表示字符串,那么如果我的项目是UNICODE的,那么我就需要先把 lpszText 转换为 const char* (用CT2CA宏)然后再调用它的方法。

还有,如果你从一个文件读入字符串,ReadFile 实际读入的是 char 类型,那么你就需要知道文件的编码方式,然后根据它的编码来确定你如何把 char 类型的字符串转换成你的项目中的 TCHAR 类型的字符串。

Launcher | 园豆:45050 (高人七级) | 2012-12-20 17:10

@Launcher: 
我把抓出来的内容直接输出到控制台,可以看见是正常的中文。
应该是字符集的问题,我用std:locale方法抓取系统locale出来的是English_United States.1252,但是我不知道windows什么地方可以设置。

杨彬Allen | 园豆:261 (菜鸟二级) | 2012-12-21 10:41

@楊彬: 如果你能够为每个用户的OS都去设置一遍区域与语言的话,那么你可以通过在“区域与语言”中修改“当前位置”和“更改系统区域设置”来实现,如果列表不包含中文的话,你可能还需要额外的去安装中文语言包。

 

或者,你可以通过程序来解决,统一按照UNICODE来输出日志文件,记得在日志文件头写入正确的BOM信息。

Launcher | 园豆:45050 (高人七级) | 2012-12-21 10:59

@Launcher: 再次感谢大哥!奇怪的是我区域语言都设置了“Regional and Language Options—Advanced标签里面选择 Chinese(PRC);Language标签里面已经勾选了Install files for East Asian languages,但是灰色不可 更改。”区域也是China~~~

但是这么设置后HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Nls\Locale
"(Default)"这个值还是"409",后来我把他手动改成804就可以显示中文了。。。

杨彬Allen | 园豆:261 (菜鸟二级) | 2012-12-21 13:41

@楊彬: 设置完成后要重启。Windows 2003早就不使用了,所以我们的程序都是通过程序来解决这些问题,而不是要求用户去修改它的操作系统(用户可能还有Win2000/XP/Vista/7/2008/8),因此也就不记得Windows 2003如何设置。你可以仔细阅读下Windows 2003的帮助文档。

我们只在Office上遇到过一些问题,因为OS区域,语言包,界面语言对Office版本(中文,英文)的影响还是不一样的。

Launcher | 园豆:45050 (高人七级) | 2012-12-21 14:02

@Launcher: 多谢指教。

1. 我发现了,因为我程序编译的用户locale是简体中文的,但是我测试服务器系统locale是英文的,所以造成了乱码。如果用unicode编码应该是可以解决这个问题的。

2. 设置完区域、语言等设置后,我是重启过机器的,现在我的问题变成为什么设置完过后system locale值不变。

杨彬Allen | 园豆:261 (菜鸟二级) | 2012-12-21 14:11
Launcher | 园豆:45050 (高人七级) | 2012-12-21 14:27
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册