我有一段简单的代码可以打开文件流&打印出来的东西。 一旦它击中一个unicode角色,它就会停止阅读。
我的系统设置为日语语言环境& Visual Studio设置为unicode编译。不知道最近发生了什么。
文件:
<abc \ 单位孤>hajslklfasjflkesjfleajflj
文件十六进制转储:
EF BB BF 3C 61 62 63 20 5C 20 E5 8D 95 E4 BD 8D
E5 AD A4 3E 68 61 6A 73 6C 6B 6C 66 61 73 6A 66
6C 6B 65 73 6A 66 6C 65 61 6A 66 6C 6A 0D 0A
代码部分:
std::wifstream fin(path, std::ios::binary);
fin.imbue(std::locale(fin.getloc(), new std::codecvt_utf8_utf16<wchar_t, 0x10ffff, std::consume_header>));
if (!fin.good()) return;
while (fin.good()) {
std::wcout << (wchar_t)fin.get() << "\n";
}
fin.close();
输出:
答案 0 :(得分:2)
它读得很好,它只是不写作。
std::wcout << (wchar_t)fin.get() << "\n";
不幸的是std::wcout
实际上并没有可靠地将Unicode发送到终端。
尽管Windows终端本身以UTF-16代码单元工作,但std::wcout
仍然以纯字节为基础的术语定义。它在使用特定于语言环境的默认编码之前将其宽输入转换为字节,然后再写入好的旧的Unicode无知字节标准输出流(毕竟可以是本机字节文件重定向以及本机Unicode终端输出)
所以std::wcout
最终在Windows下与所有其他字节IO接口一样受限制,仅限于当前代码页中的字符。您的代码页可能是932,其中字符单
U + 5355不存在,因此尝试编写它会破坏流。
将当前代码页设置为65001以尝试获得所有其他现代平台所需的相同UTF-8输出,但由于基本C运行时中存在各种多字节字符计数错误而无法正常工作。 MS已经将这个版本留下了许多版本,所以期望UTF-8在Windows下仍然是二等公民。
一些替代方案:
使用Win32 WriteConsoleW
API而不是stdlib接口。 (需要小心处理可能的输出重定向,如果您需要跨项目兼容的项目。)
将_setmode
与_O_U16TEXT
一起使用可将输出流更改为UTF-16编码的字节。请参阅this question中的示例。似乎并非所有接口都必须在此模式下工作;如果你试图同时使用字节接口,你可能会遇到麻烦。
显式输出UTF-8编码的字节,并要求Windows控制台用户只是忍受导致的mojibake和缺少的字形。
遗憾的是,这个故事仍然很悲惨。
答案 1 :(得分:0)
std :: wcout可能与它有关。
试试此页面:https://alfps.wordpress.com/2011/12/08/unicode-part-2-utf-8-stream-mode/
//std::locale loc2 = std::locale("zh-CN");
//SetConsoleOutputCP(CP_UTF8);
//SetConsoleCP(65001);
_setmode(_fileno(stdout), _O_U16TEXT);
std::wcout << "text:" << L"<abc单位孤>hajslklfasjflkesjfleajflj" << "\n";
_setmode(_fileno(stdout), _O_WTEXT);
std::wcout << "text:" << L"<abc单位孤>hajslklfasjflkesjfleajflj" << "\n";
_setmode(_fileno(stdout), _O_U8TEXT);
std::wcout << "text:" << L"<abc单位孤>hajslklfasjflkesjfleajflj" << "\n";
//setlocale(LC_ALL, "C");
//fputs("hello 2: ΓΔΕΘΛΞΠΣΦΨЪЩШЫЮЯ\n", stdout);
std::wcout << "text:" << L"hello 2: ΓΔΕΘΛΞΠΣΦΨЪЩШЫЮЯ" << "\n";
wprintf(L">>> hello 2: ΓΔΕΘΛΞΠΣΦΨЪЩШЫЮЯ \n");
std::locale loc3 = std::locale("en-US");
_setmode(_fileno(stdout), _O_U16TEXT);
std::wcout << "text:" << L"<abc单位孤>hajslklfasjflkesjfleajflj" << "\n";
_setmode(_fileno(stdout), _O_WTEXT);
std::wcout << "text:" << L"<abc单位孤>hajslklfasjflkesjfleajflj" << "\n";
_setmode(_fileno(stdout), _O_U8TEXT);
std::wcout << "text:" << L"<abc单位孤>hajslklfasjflkesjfleajflj" << "\n";
//setlocale(LC_ALL, "C");
//fputs("hello 2: ΓΔΕΘΛΞΠΣΦΨЪЩШЫЮЯ\n", stdout);
std::wcout << "text:" << L"hello 2: ΓΔΕΘΛΞΠΣΦΨЪЩШЫЮЯ" << "\n";
wprintf(L">>> hello 2: ΓΔΕΘΛΞΠΣΦΨЪЩШЫЮЯ \n");
取决于您输入 chcp intvalue 命令的方式,您将获得与代码页1252和65001直接相关的输出
我确实写了一周或两周的unicode测试。它可能会对您有所帮助,请参阅https://github.com/MagnusTiberius/wcutil/blob/master/widechartest.cpp了解详细信息。
您可能还想查看如何设置代码页以呈现双/多字节。
http://www.curlybrace.com/words/2014/10/03/windows-console-and-doublemulti-byte-character-set/