我正在使用Visual Studio C ++ 2008(Express)。当我运行下面的代码时,wostream(std::wcout
和std::wfstream
)停止输出遇到的第一个非ASCII字符(在这种情况下是中文)。纯ASCII字符打印正常。但是,在调试器中,我可以看到wstring
实际上已正确填充了中文字符,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();
}
答案 0 :(得分:3)
默认情况下,std :: wcout和std :: wofstream用于某些操作的语言环境是“C”语言环境,不需要支持非ascii字符(或C ++基本字符集之外的任何字符)。将语言环境更改为支持您要使用的字符的语言环境。
不幸的是,在Windows上最简单的事情是使用遗留代码页,但是你真的应该避免这种情况。遗留代码页是坏消息。相反,你应该使用Unicode,无论是UTF-8,UTF-16还是其他。此外,你将不得不解决Windows不幸的控制台模型,这使得写入控制台与写入其他类型的输出流非常不同。您可能需要查找或编写自己的输出缓冲区,专门处理控制台(或者提交一个错误,要求Microsoft修复它)。
以下是控制台输出的示例:
#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"привет, 猫咪!\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.
}
你可以将UTF-8输出到这样的文件中(尽管我不确定VS2008是否支持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"привет, 猫咪!";
}
答案 1 :(得分:1)
包含以下头文件
#include <locale>
在main的开头,添加以下行。
std::locale::global(std::locale("chinese"));
这有助于设置正确的区域设置。