[英]How to portably write std::wstring to file?
我有一個聲明的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。
對於std::wstring
您需要std::wofstream
std::wofstream f(L"C:\\some file.txt");
f << str;
f.close();
std::wstring
用於UTF-16或UTF-32, 而不是 UTF-8。 對於UTF-8,您可能只想使用std::string
,並通過std::cout
寫出來。 只是FWIW,C ++ 0x將具有Unicode文字,這應該有助於澄清這樣的情況。
為什么不把文件寫成二進制文件。 只需在std :: ios :: binary設置中使用ofstream即可。 編輯應該能夠解釋它。 不要忘記開頭的Unicode標志0xFEFF。 你最好用圖書館寫作,試試其中一個:
http://www.codeproject.com/KB/files/EZUTF.aspx
C ++具有在輸出或文件寫入時執行從寬字符到本地字符的轉換的方法。 為此目的使用 codecvt facet。
您可以使用標准的std :: codecvt_byname或非標准的codecvt_facet 實現 。
#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”。
有一個(Windows專用)解決方案,它應該為你工作在這里 。 基本上,將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;
}
請注意,寬流只輸出char *變量,因此您可能應該嘗試使用c_str()
成員函數轉換std::wstring
,然后將其輸出到文件中。 它應該可行嗎?
我前段時間遇到了同樣的問題,並寫下了我在博客上找到的解決方案。 您可能需要查看它是否有幫助,尤其是函數wstring_to_utf8
。
http://pileborg.org/b2e/blog5.php/2010/06/13/unicode-utf-8-and-wchar_t
根據我使用不同字符編碼的經驗,我建議您只在加載時處理UTF-8並節省時間。 如果您嘗試將內部表示存儲在UTF-8中,那么您將陷入痛苦的世界,因為單個字符可以是1字節到4之間的任何內容。因此像strlen這樣的簡單操作需要查看每個字節來決定len而不是分配緩沖區(盡管您可以通過查看char序列中的第一個字節進行優化,例如00..7f是單字節char,c2..df表示2字節char等)。
人們經常在稱為UTF-16時引用“Unicode字符串”,而在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項目:
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.