wostream 无法输出 wstring
我使用的是 Visual Studio C++ 2008 (Express).当我运行以下代码时,wostream(std::wcout
和 std::wfstream
)在第一个非 ASCII 字符(在本例中为中文)停止输出) 遭遇.纯 ASCII 字符打印正常.但是,在调试器中,我可以看到 wstring
实际上已正确填充了中文字符,并且 输出 <<...
实际上正在执行.
I am using Visual Studio C++ 2008 (Express). When I run the below code, the wostream (both std::wcout
, and std::wfstream
) stops outputting at the first non-ASCII character (in this case Chinese) encountered. Plain ASCII characters print fine. However, in the debugger, I can see that the wstring
s are in fact properly populated with Chinese characters, and the output << ...
is in fact getting executed.
Visual Studio 解决方案中的项目设置设置为使用 Unicode 字符集".为什么 std::wostream
无法输出 ASCII 范围之外的 Unicode 字符?
The project settings in the Visual Studio solution are set to "Use Unicode Character Set". Why is std::wostream
failing to output Unicode characters outside of the ASCII range?
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" ";
}
//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();
}
推荐答案
默认情况下,std::wcout 和 std::wofstream 用于某些操作的语言环境是C"语言环境,不需要支持非ascii 字符(或 C++ 基本字符集之外的任何字符).将区域设置更改为支持您要使用的字符的区域设置.
By default the locale that std::wcout and std::wofstream use for certain operations is the "C" locale, which is not required to support non-ascii characters (or any character outside C++'s basic character set). Change the locale to one that supports the characters you want to use.
不幸的是,在 Windows 上最简单的事情是使用旧代码页,但您确实应该避免这种情况.遗留代码页是个坏消息.相反,您应该使用 Unicode,无论是 UTF-8、UTF-16 还是其他.此外,您还必须解决 Windows 不幸的控制台模型,该模型使写入控制台与写入其他类型的输出流非常不同.您可能需要找到或编写自己的输出缓冲区来专门处理控制台(或者提交一个错误,要求 Microsoft 修复它).
The simplest thing to do on Windows is unfortunately to use legacy codepages, however you really should avoid that. Legacy codepages are bad news. Instead you should use Unicode, whether UTF-8, UTF-16, or whatever. Also you'll have to work around Windows' unfortunate console model that makes writing to the console very different from writing to other kinds of output streams. You might need to find or write your own output buffer that specifically handles the console (or maybe file a bug asking Microsoft to fix it).
这是控制台输出的示例:
Here's an example of console output:
#include <Windows.h>
#include <streambuf>
#include <iostream>
class Console_streambuf
: public std::basic_streambuf<wchar_t>
{
HANDLE m_out;
public:
Console_streambuf(HANDLE out) : m_out(out) {}
virtual int_type overflow(int_type c = traits_type::eof())
{
wchar_t wc = c;
DWORD numberOfCharsWritten;
BOOL res = WriteConsoleW(m_out, &wc, 1, &numberOfCharsWritten, NULL);
(void)res;
return 1;
}
};
int main() {
Console_streambuf out(GetStdHandle(STD_OUTPUT_HANDLE));
auto old_buf = std::wcout.rdbuf(&out);
std::wcout << L"привет, 猫咪!
";
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.
}
您可以将 UTF-8 输出到这样的文件(虽然我不确定 VS2008 是否支持 codecvt_utf8_utf16):
You can do UTF-8 output to a file like this (although I'm not sure VS2008 supports codecvt_utf8_utf16):
#include <codecvt>
#include <fstream>
int main() {
std::wofstream myFile("data.bin", std::ios::out | std::ios::binary);
myFile.imbue(std::locale(myFile.getloc(),new std::codecvt_utf8_utf16<wchar_t>));
myFile << L"привет, 猫咪!";
}
相关文章