ofstream和wofstream与中文输出问题

简介: 转载文章地址:http://hi.baidu.com/vfishg/item/81ddb9271835fbf951fd8765 使用C++标准库的iostream,可以方便地将控制台、文件、字符串以及其它可扩充的外部表示作为流来处理,但要处理中文,却会碰到很多问题。

转载文章地址:http://hi.baidu.com/vfishg/item/81ddb9271835fbf951fd8765

使用C++标准库的iostream,可以方便地将控制台、文件、字符串以及其它可扩充的外部表示作为流来处理,但要处理中文,却会碰到很多问题。 本人原来没怎么用过这个iostream,这几天尝试用这个写点东西,一会儿不能输出中文,一会儿不支持中文文件名的,搞得头大。网上搜了搜,没有发现适 用于所有情况的解决方案。不过后来自己经过多次测试,基本解决了这些问题,现在写成文字作为一个总结,也供碰到同样问题的朋友参考。关于C语言中的 printf和wprintf的中文输出,本文也进行了探讨。


需要说明的是,我的开发环境是VS 2005(标准库当然也是微软实现的),不保证其它环境下是相同的效果

  1. cout和wcout在缺省的C locale下,cout可以直接输出中文,但对于wcout却不行(至少VS 2005下不行)。

    对于wcout,需要将其locale设为本地语言才能输出中文:
    wcout.imbue(locale(locale(),"",LC_CTYPE)); // 1
    也有人用如下语句的,但这会改变wcout的所有locale设置,比如数字“1234”会输出为“1,234”。
    wcout.imbue(locale(""));

  2. ofstream和wofstream在缺省的C locale下,ofstream能正确输出中文到文件中,但不支持中文文件名;wofstream支持中文文件名,但不能向文件中输出中文。

    要解决这个 问题,需要在打开文件之前将全局locale设为本地语言。将全局locale设为本地语言后,ofstream和wofstream的问题都解决了。
    但 cout和wcout却不能输出中文了。要让cout和wcout输出中文,需要将全局locale恢复原来的设置,如下所示:
    locale &loc=locale::global(locale(locale(),"",LC_CTYPE)); // 2
    ofstream ofs("ofs测试.txt");
    wofstream wofs(L"wofs测试.txt");locale::global(loc); // 3
    ofs<<"test测试"<<1234<<endl;
    wofs<<L"Another test还是测试"<<1234<<endl;
  1. printf和wprintf

    加上这两位C语言中的老兄,问题更加复杂。考虑如下语句(注意s的大小写):
    printf("%s", "multibyte中文\n"); // 4
    printf("%S", L"unicode中文\n"); // 5
    wprintf(L"%S", "multibyte中文\n"); // 6
    wprintf(L"%s", L"unicode中文\n"); // 7
    缺省情况下,⑤、⑦两条语句不能输出中文,这两条语句中字符串的形式是unicode形式的。

    如果在所有输出语句之前加上如下语句将C语言的全局locale设置为本地语言(C语言中只有全局locale)就可以正常输出了:
    setlocale(LC_CTYPE, ""); // 8
    但这会导致cout和wcout不能输出中文(汗,的确麻烦),将C语言的全局locale恢复后cout和wcout就正常了,如下所示:
    setlocale(LC_CTYPE, "C"); // 9
    但恢复后,printf和wprintf输出Unicode文本又不正常了(输出MultiByte文本总是正常的)。总不能每写一个 printf/wprintf就设置一次然后再恢复一次吧?所以,建议不要混用iostream和printf/wprintf,实在要混用,那就让 printf/wprintf只输出MultiByte字符串,这样不需要调用setlocale(),也就不会影响到cout和wcout。

总之,用iostream、printf/wprintf输出中文,有点麻烦。概括起来要点如下:

  1. 如果要用wcout,需要在使用之前按语句(1)将其locale设置为本地语言;
  2.  如果要用ofstream或wofstream,要在打开文件之前按语句(2)将全局locale设为本地语言并保存初始的全局locale。然后在打开文件之后,按语句(3)将全局locale恢复为初始值; 
  3. 不要混用iostream和printf/wprintf。如果要混用,只用printf/wprintf输出MultiByte字符串;单独使用printf/wprintf时,如果要输出Unicode字
相关文章
解决CodeBlock安装完成后不能进行注释和printf输出中文的解决方式
前几天重新用回CodeBlock发现编写注释后不能正常编译,修改后又不可以使用printf输出中文 现将解决方式记录备用
119 0
|
5月前
|
存储 C语言 知识图谱
C primer plus 学习笔记 第4章 字符串和格式化输入/输出
C primer plus 学习笔记 第4章 字符串和格式化输入/输出
|
Java C++ Python
C++ 使用getline():从文件中读取一行字符串
getline() 方法从 cin 输入流缓冲区中读取一行字符串。在此基础上,getline() 方法还适用于读取指定文件中的一行数据,本节就给大家做详细的讲解。 我们知道,getline() 方法定义在 istream 类中,而 fstream 和 ifstream 类继承自 istream 类,因此 fstream 和 ifstream 的类对象可以调用 getline() 成员方法。 当文件流对象调用 getline() 方法时,该方法的功能就变成了从指定文件中读取一行字符串。该方法有以下 2 种语法格式: istream & getline(char* buf, int bufS
234 0
【Word】Word公式导出PDF后出现井号括号#()错误
【Word】Word公式导出PDF后出现井号括号#()错误
211 0
|
Java BI 数据处理
【JavaSE专栏73】字符输出流Writer,将字符数据输出至目标
【JavaSE专栏73】字符输出流Writer,将字符数据输出至目标
【JavaSE专栏73】字符输出流Writer,将字符数据输出至目标
C++ 中 ifstream读取txt文件内容
C++ 中 ifstream读取txt文件内容
1335 0
C++ 中 ifstream读取txt文件内容
|
C++
当输入中有空行时,如何在 C++ 中使用 getline()?
在 C++ 中,如果我们需要从一个流中读取好几个句子,我们通常会首选的方法是使用 getline() 函数。因为它可以读取直到遇到换行符或看到用户提供的分隔符
405 0
|
算法
三行代码将Excel转为任意格式的Word
大家好,我是志斌~ 今天来跟大家分享一个实际案例需求,本文来自小明大佬的创作~
201 0
三行代码将Excel转为任意格式的Word
|
Python
[PYTHON实战]从键盘输入一个字符串,将小写字母全部转换成大写字母,然后输出到一个磁盘文件"test"中保存。
从键盘输入一个字符串,将小写字母全部转换成大写字母,然后输出到一个磁盘文件"test"中保存。
1559 0
|
文字识别
PDF转换成Word后乱码怎么办?
我们在把PDF文档转换为Word的过程中,偶尔会遇到PDFelement转换后乱码或者排版混乱的现象,给我们造成了极大的困扰。 为什么PDF转换成Word会乱码?乱码了之后要怎么办呢?下面就由软发网为大家讲解一下。
1274 0