我目前正在编写一个应用程序,它要求我在任意窗口上调用GetWindowText,并将这些数据存储到一个文件中供以后处理。 长话短说,我注意到我的工具在“战地风云3”上失败了,我把它缩小到窗口标题中的下列字符: http : //www.fileformat.info/info/unicode/char/2122/index。 HTM
所以我创build了一个小testing应用程序,只是做了以下几点:
std::wcout << L"\u2122";
低,看到输出到控制台窗口剩余的程序。
为什么MSVC STL窒息这个字符(我假设其他人),如MessageBoxW等API显示它就好了?
我怎样才能把这些字符打印到我的文件?
在Windows 7 x64下testingVC10和VC11。
对不起,这个build设不好的职位,我正在把我的头发撕在这里。
谢谢。
编辑:
最小的testing用例
#include <fstream> #include <iostream> int main() { { std::wofstream test_file("test.txt"); test_file << L"\u2122"; } std::wcout << L"\u2122"; }
预期结果:打印到控制台和文件的“™”字符。 观察结果:文件被创build但是是空的。 没有输出到控制台。
我已经确认,我用于我的控制台的字体能够显示有问题的字符,并且文件肯定是空的(0字节大小)。
编辑:
进一步的debugging表明在stream中设置了'failbit'和'badbit'。
编辑:
我也尝试过使用Boost.Locale,即使在新的语言环境被全局灌注并明确指向所有标准stream的情况下,我也遇到了同样的问题。
要写入文件,必须正确设置区域设置,例如,如果要将它们编写为UTF-8字符,则必须添加
const std::locale utf8_locale = std::locale(std::locale(), new std::codecvt_utf8<wchar_t>()); test_file.imbue(utf8_locale);
你必须添加这2个包含文件
#include <codecvt> #include <locale>
要写入控制台,您必须通过添加,以正确的模式(这是特定于Windows)设置控制台
_setmode(_fileno(stdout), _O_U8TEXT);
(如果你想使用UTF-8)。
为此,您必须添加这2个包含文件:
#include <fcntl.h> #include <io.h>
此外,您必须确保您使用的是支持Unicode的字体(例如Lucida控制台)。 您可以在控制台窗口的属性中更改字体。
完整的程序现在看起来像这样:
#include <fstream> #include <iostream> #include <codecvt> #include <locale> #include <fcntl.h> #include <io.h> int main() { const std::locale utf8_locale = std::locale(std::locale(), new std::codecvt_utf8<wchar_t>()); { std::wofstream test_file("c:\\temp\\test.txt"); test_file.imbue(utf8_locale); test_file << L"\u2122"; } _setmode(_fileno(stdout), _O_U8TEXT); std::wcout << L"\u2122"; }
你总是使用std::wcout
或者你有时使用std::cout
? 混合这些将无法正常工作。 当然,错误描述“窒息”根本不说你观察到什么问题。 但是,我怀疑这是使用文件的问题。
由于没有真正的问题描述,需要一些水晶球,然后在黑暗中击中问题…因为你想从你的文件中获取Unicode字符请确保你正在使用的文件流使用一个std::locale
其std::codecvt<...>
方面实际上转换为适当的Unicode编码。
我刚刚测试了GCC(版本4.4到4.7)和MSVC 10,都显示出这个问题。
同样是破坏的是wprintf
,它和C ++流API一样小。
我也测试了原始的Win32 API,看看是否没有其他的东西导致失败,这个工程:
#include <windows.h> int main() { HANDLE stdout = GetStdHandle(STD_OUTPUT_HANDLE); DWORD n; WriteConsoleW( stdout, L"\u03B2", 1, &n, NULL ); }
把β
写到控制台(如果你把cmd的字体设置成Lucida Console)。
结论:在大型C ++标准库实现中, wchar_t
输出被严重破坏。
虽然宽字符流将Unicode作为输入,但这不是他们产生的输出 – 字符经过转换。 如果一个字符不能被转换成的编码表示,输出失败。