我声明了wstring
:
// random wstring
std::wstring str = L"abcàdëefŸg€hhhhhhhµa";
文字将是UTF-8编码,因为我的源文件是。
[编辑:根据Mark Ransom的说法不一定是这样,编译器将决定使用什么编码 - 让我们假设我从例如编码的文件中读取该字符串。 UTF-8]
我非常希望将其转换为文件读取(当文本编辑器设置为正确的编码时)
abcàdëefŸg€hhhhhhhµa
但是ofstream
不是很合作(拒绝接受wstring
个参数),wofstream
据说需要知道区域设置和编码设置。我只想输出这组字节。通常如何做到这一点?
编辑:它必须是跨平台的,不应该依赖于UTF-8 的编码。我碰巧有一组字节存储在wstring
中,并希望输出它们。它很可能是UTF-16,或纯ASCII。
答案 0 :(得分:29)
对于std::wstring
,您需要std::wofstream
std::wofstream f(L"C:\\some file.txt");
f << str;
f.close();
答案 1 :(得分:14)
std::wstring
适用于UTF-16或UTF-32,不是 UTF-8。对于UTF-8,您可能只想使用std::string
,并通过std::cout
写出来。只是FWIW,C ++ 0x将具有Unicode文字,这应该有助于澄清这样的情况。
答案 2 :(得分:7)
为什么不将文件写为二进制文件。只需在std :: ios :: binary设置中使用ofstream即可。编辑应该能够解释它。不要忘记开头的Unicode标志0xFEFF。 你最好用图书馆写作,试试其中一个:
http://www.codeproject.com/KB/files/EZUTF.aspx
答案 3 :(得分:4)
C ++具有在输出或文件写入时执行从宽字符到本地字符的转换的方法。 Use为此目的的codecvt方面。
您可以使用标准std::codecvt_byname或非标准codecvt_facet implementation。
#include <locale>
using namespace std;
typedef codecvt_facet<wchar_t, char, mbstate_t> Cvt;
locale utf8locale(locale(), new codecvt_byname<wchar_t, char, mbstate_t> ("en_US.UTF-8"));
wcout.imbue(utf8locale);
wcout << L"Hello, wide to multybyte world!" << endl;
请注意,在某些平台上,codecvt_byname只能为系统中安装的区域设置发出转换。因此,我建议在stackoverflow中搜索“utf8 codecvt “并从列出的自定义codecvt实现的许多参考资料中做出选择。
编辑: 由于OP声明字符串已经编码,他应该做的就是从代码的每个标记中删除前缀L和“w”。
答案 4 :(得分:2)
有一个(特定于Windows的)解决方案应该适合您here。基本上,将wstring
转换为UTF-8代码页,然后使用ofstream
。
#include < windows.h >
std::string to_utf8(const wchar_t* buffer, int len)
{
int nChars = ::WideCharToMultiByte(
CP_UTF8,
0,
buffer,
len,
NULL,
0,
NULL,
NULL);
if (nChars == 0) return "";
string newbuffer;
newbuffer.resize(nChars) ;
::WideCharToMultiByte(
CP_UTF8,
0,
buffer,
len,
const_cast< char* >(newbuffer.c_str()),
nChars,
NULL,
NULL);
return newbuffer;
}
std::string to_utf8(const std::wstring& str)
{
return to_utf8(str.c_str(), (int)str.size());
}
int main()
{
std::ofstream testFile;
testFile.open("demo.xml", std::ios::out | std::ios::binary);
std::wstring text =
L"< ?xml version=\"1.0\" encoding=\"UTF-8\"? >\n"
L"< root description=\"this is a naïve example\" >\n< /root >";
std::string outtext = to_utf8(text);
testFile << outtext;
testFile.close();
return 0;
}
答案 5 :(得分:0)
请注意,宽流只输出char *变量,因此您可以尝试使用c_str()
成员函数转换std::wstring
,然后将其输出到文件中。它应该可行吗?
答案 6 :(得分:0)
前段时间我遇到了同样的问题,并写下了我在博客上找到的解决方案。您可能需要查看它是否有帮助,尤其是函数wstring_to_utf8
。
http://pileborg.org/b2e/blog5.php/2010/06/13/unicode-utf-8-and-wchar_t
答案 7 :(得分:0)
如果要编写可移植代码,则不应使用UTF-8编码的源文件。遗憾。
std::wstring str = L"abcàdëefŸg€hhhhhhhµa";
(我不确定这是否真的会伤害标准,但我认为是。但即使是安全的,也不应该。)
是的,纯粹使用std::ostream
将无效。有很多方法可以将wstring
转换为UTF-8。我最喜欢的是使用 International Components for Unicode 。这是一个很大的库,但它很棒。你会得到很多额外的东西以及将来可能需要的东西。
答案 8 :(得分:0)
根据我使用不同角色编码的经验,我建议您只在加载时处理UTF-8并节省时间。如果您尝试将内部表示存储在UTF-8中,那么您将陷入痛苦的世界,因为单个字符可以是1字节到4之间的任何内容。因此像strlen这样的简单操作需要查看每个字节来决定len而不是分配缓冲区(尽管您可以通过查看char序列中的第一个字节进行优化,例如00..7f是单字节char,c2..df表示2字节char等)。
当人们经常提到'Unicode字符串'时,他们指的是UTF-16,而在Windows上,wchar_t是固定的2字节。在Windows中,我认为wchar_t只是:
typedef SHORT wchar_t;
完整的UTF-32 4字节表示很少需要且非常浪费,这就是Unicode标准(5.0)所说的:
“平均超过99%的UTF-16使用单一代码单位表示...... UTF-16提供紧凑尺寸的正确组合,能够处理BMP之外的偶然角色”
简而言之,使用whcar_t作为内部表示并在加载和保存时进行转换(除非您知道需要,否则不要担心完整的Unicode)。
关于执行实际转换,请查看ICU项目: