Nat*_*han 5 c++ unicode visual-studio-2008 wofstream
我正在使用Visual Studio C++ 2008(Express).当我运行下面的代码时,wostream(both std::wcout和std::wfstream)在遇到第一个非ASCII字符(在这种情况下是中文)时停止输出.纯ASCII字符打印正常.但是,在调试器中,我可以看到wstrings实际上已正确填充了中文字符,并且output << ...实际上正在执行.
Visual Studio解决方案中的项目设置设置为"使用Unicode字符集".为什么std::wostream无法输出ASCII范围之外的Unicode字符?
void PrintTable(const std::vector<std::vector<std::wstring>> &table, std::wostream& output) {
for (unsigned int i=0; i < table.size(); ++i) {
for (unsigned int j=0; j < table[i].size(); ++j) {
output << table[i][j] << L"\t";
}
//output << std::endl;
}
}
void TestUnicodeSingleTableChinesePronouns() {
FileProcessor p("SingleTableChinesePronouns.docx");
FileProcessor::iterator fileIterator;
std::wofstream myFile("data.bin", std::ios::out | std::ios::binary);
for(fileIterator = p.begin(); fileIterator != p.end(); ++fileIterator) {
PrintTable(*fileIterator, myFile);
PrintTable(*fileIterator, std::wcout);
std::cout<<std::endl<<"---------------------------------------"<<std::endl;
}
myFile.flush();
myFile.close();
}
Run Code Online (Sandbox Code Playgroud)
默认情况下,std::wcout 和 std::wofstream 用于某些操作的语言环境是“C”语言环境,不需要支持非 ascii 字符(或 C++ 基本字符集之外的任何字符)。将区域设置更改为支持您要使用的字符的区域设置。
\n\n不幸的是,在 Windows 上做的最简单的事情就是使用旧代码页,但是您确实应该避免这样做。遗留代码页是个坏消息。相反,您应该使用 Unicode,无论是 UTF-8、UTF-16 还是其他。此外,您还必须解决 Windows 不幸的控制台模型,该模型使得写入控制台与写入其他类型的输出流非常不同。您可能需要找到或编写自己的输出缓冲区来专门处理控制台(或者可能提交一个错误要求微软修复它)。
\n\n这是控制台输出的示例:
\n\n#include <Windows.h>\n\n#include <streambuf>\n#include <iostream>\n\nclass Console_streambuf\n : public std::basic_streambuf<wchar_t>\n{\n HANDLE m_out;\npublic:\n Console_streambuf(HANDLE out) : m_out(out) {}\n\n virtual int_type overflow(int_type c = traits_type::eof())\n {\n wchar_t wc = c;\n DWORD numberOfCharsWritten;\n BOOL res = WriteConsoleW(m_out, &wc, 1, &numberOfCharsWritten, NULL);\n (void)res;\n return 1;\n }\n};\n\nint main() {\n Console_streambuf out(GetStdHandle(STD_OUTPUT_HANDLE));\n auto old_buf = std::wcout.rdbuf(&out);\n std::wcout << L"\xd0\xbf\xd1\x80\xd0\xb8\xd0\xb2\xd0\xb5\xd1\x82, \xe7\x8c\xab\xe5\x92\xaa!\\n";\n std::wcout.rdbuf(old_buf); // replace old buffer so that destruction can happen correctly. FIXME: use RAII to do this in an exception safe manner.\n}\nRun Code Online (Sandbox Code Playgroud)\n\n您可以将 UTF-8 输出到这样的文件(尽管我不确定 VS2008 支持 codecvt_utf8_utf16):
\n\n#include <codecvt>\n#include <fstream>\n\nint main() {\n std::wofstream myFile("data.bin", std::ios::out | std::ios::binary);\n myFile.imbue(std::locale(myFile.getloc(),new std::codecvt_utf8_utf16<wchar_t>));\n\n myFile << L"\xd0\xbf\xd1\x80\xd0\xb8\xd0\xb2\xd0\xb5\xd1\x82, \xe7\x8c\xab\xe5\x92\xaa!";\n}\nRun Code Online (Sandbox Code Playgroud)\n