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语言
Linux应用开发基础知识——字符文字编码(五)
Linux应用开发基础知识——字符文字编码(五)
156 0
Linux应用开发基础知识——字符文字编码(五)
|
3月前
|
存储
字符编码问题之mbtowc 函数中计算最终的 Unicode 值如何解决
字符编码问题之mbtowc 函数中计算最终的 Unicode 值如何解决
17 0
|
存储 前端开发 JavaScript
input输入unicode零宽字符前端踩坑
Unicode字符中有一类特殊的字符叫做零宽字符 ZWJ(zero width joiner),也叫非打印字符、不可见字符。正则的断言即叫零宽断言,意思即本身并不占用宽度,如比较出名的零宽空格
439 0
|
存储 Windows
“浅入深处“编码历史,字符串编码(ASCII, GBK, ANSI, Unicode, UTF-8编码),为什么记事本默认ANSI编码,Unicode和UTF8有什么区别
“浅入深处“编码历史,字符串编码(ASCII, GBK, ANSI, Unicode, UTF-8编码),为什么记事本默认ANSI编码,Unicode和UTF8有什么区别
142 0
|
机器学习/深度学习 人工智能 自然语言处理
[oeasy]python0129_unicode_中文字符序号_十三道大辙_字符编码解码_eval_火星文
[oeasy]python0129_unicode_中文字符序号_十三道大辙_字符编码解码_eval_火星文
137 0
[oeasy]python0129_unicode_中文字符序号_十三道大辙_字符编码解码_eval_火星文
|
存储
[oeasy]python0133_[趣味拓展]好玩的unicode字符_另类字符_上下颠倒英文字符
[oeasy]python0133_[趣味拓展]好玩的unicode字符_另类字符_上下颠倒英文字符
966 0
[oeasy]python0133_[趣味拓展]好玩的unicode字符_另类字符_上下颠倒英文字符
|
存储 Unix 开发工具
[oeasy]python0111_字型码_字符字型编码_点阵字库_ascii演化
[oeasy]python0111_字型码_字符字型编码_点阵字库_ascii演化
161 0
 [oeasy]python0111_字型码_字符字型编码_点阵字库_ascii演化
|
编解码
Debug栏打印时自动把Unicode编码转化成汉字
Debug栏打印时自动把Unicode编码转化成汉字
159 0
Debug栏打印时自动把Unicode编码转化成汉字
[oeasy]python0018_ ASCII_字符分布_数字_大小写字母_符号_黑暗森林
[oeasy]python0018_ ASCII_字符分布_数字_大小写字母_符号_黑暗森林
120 0
[oeasy]python0018_ ASCII_字符分布_数字_大小写字母_符号_黑暗森林
【斗鱼笔试题】字符串分类---字符集相同的字符串为同一类
【斗鱼笔试题】字符串分类---字符集相同的字符串为同一类
79 0