wofstream,wcout无法输出unicode的真相

简介: 之前我转载过一篇ofstream和wofstream与中文输出问题,让我初步知道如何解决这类问题。第一次我没有在意,按照文章中做的方法去做,然后程序就运行正常了。

之前我转载过一篇ofstream和wofstream与中文输出问题,让我初步知道如何解决这类问题。第一次我没有在意,按照文章中做的方法去做,然后程序就运行正常了。我试图去记住这些规则,但是我后来发现,太难了。以至于我在最近一次使用到 std::wofstream 类的时候,发现我无法往其中输入unicode字符。让我找了几个小时的bug,于是我今天就花了两个小时,在网上搜索资料,以及自己写一些测试工程,调试跟踪 std::wofstream 的相关函数,差不多明白了原因。下面让我用最简单的方式,让你真正理解,wofstream,wcout无法输出unicode字符的原因。

  1. 首先visual studio(也可以说微软)版本的 wofstream,wcout最终输出的字符编码都是ANSI(多字节编码,MultiByte)例如:
        std::wofstream fOut;
        fOut.open( L"你好1.txt", std::ios::trunc );
        fOut << L"徐杰" << std::endl;
        fOut.close();

    这样简短的代码,最后输出的文件编码方式是:ANSI。这也是最令我吃惊的。因为我以为 wofstream 比 ofstream 多一个 w,意思是可以直接写入unicode字符(宽字符,wide-char)。但实际上,多一个 w 只是表明其支持 unicode 文件名(或者说全路径文件名)。

  2. wofstream,wcout 在处理 unicode字符 时,必须进行内部编码转换(unicode -> ansi )。
    看完第一点之后,第二点是很自然的,因为 wofstream,wcout 最后都是要输出 ansi 的,所以必须进行字符编码转换。

  3. wofstream,wcout(或者说C++)进行编码转换的时候,需要知道将 unicode 转换到哪个国家的 ansi 编码(code page )。
    code page 的信息存放在 locale 的 codecvt 里面。 C++ 默认的 locale 中的 codecvt 没有保存任何国家的 code page。所以此时调用
        wofstream << L"徐杰"; 

  4. std::locale( std::locale(),"",std::locale::ctype )会创建当前系统环境下locale,这个locale中会保存这个系统 ansi 使用 code page。
        std::locale oNewLocale( std::locale(),"",std::locale::ctype );
        std::locale oPreviousLocale = std::locale::global( oNewLocale );
        //...文件打开,保存信息,关闭文件等操作。
        std::locale::global( oPreviousLocale );
    所以我们使用时,先将本地locale设置上去,然后用完之后,在设置回来(以免影响到其他系统的使用)。locale 类的相关用法请参考相关的C++标准。也可参考此链接:locale使用说明
知道原因之后,你可以更自如的选择使用 wofstream, ofstream, wcout, cout了。

相关文章
|
6月前
|
存储 自然语言处理 Linux
探究C/C++编码世界:从字符编码到中文处理之艺(三)
探究C/C++编码世界:从字符编码到中文处理之艺
149 2
|
6月前
|
自然语言处理 C++
探究C/C++编码世界:从字符编码到中文处理之艺(二)
探究C/C++编码世界:从字符编码到中文处理之艺
154 2
|
6月前
|
存储 自然语言处理 程序员
探究C/C++编码世界:从字符编码到中文处理之艺(一)
探究C/C++编码世界:从字符编码到中文处理之艺
121 1
|
3月前
|
存储
字符编码问题之mbtowc 函数中计算最终的 Unicode 值如何解决
字符编码问题之mbtowc 函数中计算最终的 Unicode 值如何解决
16 0
|
12月前
|
存储 前端开发 JavaScript
input输入unicode零宽字符前端踩坑
Unicode字符中有一类特殊的字符叫做零宽字符 ZWJ(zero width joiner),也叫非打印字符、不可见字符。正则的断言即叫零宽断言,意思即本身并不占用宽度,如比较出名的零宽空格
424 0
|
存储 数据可视化 算法
字符串之谜:如何找到出现频率最高的字符?
字符串之谜:如何找到出现频率最高的字符?
229 0
|
存储 Windows
“浅入深处“编码历史,字符串编码(ASCII, GBK, ANSI, Unicode, UTF-8编码),为什么记事本默认ANSI编码,Unicode和UTF8有什么区别
“浅入深处“编码历史,字符串编码(ASCII, GBK, ANSI, Unicode, UTF-8编码),为什么记事本默认ANSI编码,Unicode和UTF8有什么区别
138 0
|
机器学习/深度学习 人工智能 自然语言处理
[oeasy]python0129_unicode_中文字符序号_十三道大辙_字符编码解码_eval_火星文
[oeasy]python0129_unicode_中文字符序号_十三道大辙_字符编码解码_eval_火星文
133 0
[oeasy]python0129_unicode_中文字符序号_十三道大辙_字符编码解码_eval_火星文
|
存储
[oeasy]python0133_[趣味拓展]好玩的unicode字符_另类字符_上下颠倒英文字符
[oeasy]python0133_[趣味拓展]好玩的unicode字符_另类字符_上下颠倒英文字符
961 0
[oeasy]python0133_[趣味拓展]好玩的unicode字符_另类字符_上下颠倒英文字符
|
存储 Unix 开发工具
[oeasy]python0111_字型码_字符字型编码_点阵字库_ascii演化
[oeasy]python0111_字型码_字符字型编码_点阵字库_ascii演化
160 0
 [oeasy]python0111_字型码_字符字型编码_点阵字库_ascii演化