如何在Windows平台上将Unicode(UTF-8)文件读入wstring(s)?
wstring
sg24os4d1#
在C++11支持下,您可以使用std::codecvt_utf8 facet *,它封装了UTF-8编码字节字符串与UCS 2或UCS 4字符串 * 和 * 之间的转换,可用于读取和写入UTF-8文件,包括文本和二进制文件。为了使用facet,您通常会创建locale object,它将特定于文化的信息封装为一组facet,这些facet共同定义了特定的本地化环境。 一旦您有了locale对象,您就可以使用它imbue您的流缓冲区:
#include <sstream> #include <fstream> #include <codecvt> std::wstring readFile(const char* filename) { std::wifstream wif(filename); wif.imbue(std::locale(std::locale::empty(), new std::codecvt_utf8<wchar_t>)); std::wstringstream wss; wss << wif.rdbuf(); return wss.str(); }
可以这样使用:
std::wstring wstr = readFile("a.txt");
或者,你可以在处理字符串流之前设置the global C++ locale,这会 * 导致所有未来对std::locale默认构造函数的调用都返回一个全局 C++ 环境的副本 *(你不需要显式地将它注入流缓冲区):
std::locale
std::locale::global(std::locale(std::locale::empty(), new std::codecvt_utf8<wchar_t>));
vwoqyblh2#
根据@Hans Passant的评论,最简单的方法是使用_wfopen_s。以rt, ccs=UTF-8模式打开文件。下面是另一个纯C解决方案,至少可以在VC 2010中使用:
rt, ccs=UTF-8
#include <locale> #include <codecvt> #include <string> #include <fstream> #include <cstdlib> int main() { const std::locale empty_locale = std::locale::empty(); typedef std::codecvt_utf8<wchar_t> converter_type; const converter_type* converter = new converter_type; const std::locale utf8_locale = std::locale(empty_locale, converter); std::wifstream stream(L"test.txt"); stream.imbue(utf8_locale); std::wstring line; std::getline(stream, line); std::system("pause"); }
除了locale::empty()(这里locale::global()也可以工作)和basic_ifstream构造函数的wchar_t*重载之外,这甚至应该非常符合标准(当然,“标准”指的是C++0x)。
locale::empty()
locale::global()
basic_ifstream
wchar_t*
ghhaqwfi3#
以下是仅适用于Windows的特定于平台的函数:
size_t GetSizeOfFile(const std::wstring& path) { struct _stat fileinfo; _wstat(path.c_str(), &fileinfo); return fileinfo.st_size; } std::wstring LoadUtf8FileToString(const std::wstring& filename) { std::wstring buffer; // stores file contents FILE* f = _wfopen(filename.c_str(), L"rtS, ccs=UTF-8"); // Failed to open file if (f == NULL) { // ...handle some error... return buffer; } size_t filesize = GetSizeOfFile(filename); // Read entire file contents in to memory if (filesize > 0) { buffer.resize(filesize); size_t wchars_read = fread(&(buffer.front()), sizeof(wchar_t), filesize, f); buffer.resize(wchars_read); buffer.shrink_to_fit(); } fclose(f); return buffer; }
像这样使用:
std::wstring mytext = LoadUtf8FileToString(L"C:\\MyUtf8File.txt");
请注意,整个文件将加载到内存中,因此您可能不希望将其用于非常大的文件。
7ivaypg94#
#include <iostream> #include <fstream> #include <string> #include <locale> #include <cstdlib> int main() { std::wifstream wif("filename.txt"); wif.imbue(std::locale("zh_CN.UTF-8")); std::wcout.imbue(std::locale("zh_CN.UTF-8")); std::wcout << wif.rdbuf(); }
8fsztsew5#
最近处理了所有的编码,用这种方式解决。最好使用std::u32string,因为它在所有平台上都有稳定的大小,并且大多数字体都使用utf-32格式。(文件应该仍然是utf-8)
std::u32string
std::u32string readFile(std::string filename) { std::basic_ifstream<char32_t> fin(filename); std::u32string str{}; std::getline(fin, str, U'\0'); return str; }
您可以随意使用gcount以外的标准函数,并且只将tellg的结果保存到pos_type。另外,请确保将separator传递到std::getline(如果您不这样做,函数将给出异常std::bad_cast)
gcount
tellg
pos_type
std::getline
std::bad_cast
vxf3dgd46#
这个问题在Confused about C++'s std::wstring, UTF-16, UTF-8 and displaying strings in a windows GUI中得到了解决。总之,wstring基于UCS-2标准,这是UTF-16的前身。这是一个严格的两字节标准。我相信这涵盖了阿拉伯语。
5vf7fwbs7#
这有点生涩,但是将文件读取为普通的旧字节,然后将字节缓冲区转换为wchar_t*,怎么样?类似于:
#include <iostream> #include <fstream> std::wstring ReadFileIntoWstring(const std::wstring& filepath) { std::wstring wstr; std::ifstream file (filepath.c_str(), std::ios::in|std::ios::binary|std::ios::ate); size_t size = (size_t)file.tellg(); file.seekg (0, std::ios::beg); char* buffer = new char [size]; file.read (buffer, size); wstr = (wchar_t*)buffer; file.close(); delete[] buffer; return wstr; }
7条答案
按热度按时间sg24os4d1#
在C++11支持下,您可以使用std::codecvt_utf8 facet *,它封装了UTF-8编码字节字符串与UCS 2或UCS 4字符串 * 和 * 之间的转换,可用于读取和写入UTF-8文件,包括文本和二进制文件。
为了使用facet,您通常会创建locale object,它将特定于文化的信息封装为一组facet,这些facet共同定义了特定的本地化环境。 一旦您有了locale对象,您就可以使用它imbue您的流缓冲区:
可以这样使用:
或者,你可以在处理字符串流之前设置the global C++ locale,这会 * 导致所有未来对
std::locale
默认构造函数的调用都返回一个全局 C++ 环境的副本 *(你不需要显式地将它注入流缓冲区):vwoqyblh2#
根据@Hans Passant的评论,最简单的方法是使用_wfopen_s。以
rt, ccs=UTF-8
模式打开文件。下面是另一个纯C解决方案,至少可以在VC 2010中使用:
除了
locale::empty()
(这里locale::global()
也可以工作)和basic_ifstream
构造函数的wchar_t*
重载之外,这甚至应该非常符合标准(当然,“标准”指的是C++0x)。ghhaqwfi3#
以下是仅适用于Windows的特定于平台的函数:
像这样使用:
请注意,整个文件将加载到内存中,因此您可能不希望将其用于非常大的文件。
7ivaypg94#
8fsztsew5#
最近处理了所有的编码,用这种方式解决。最好使用
std::u32string
,因为它在所有平台上都有稳定的大小,并且大多数字体都使用utf-32格式。(文件应该仍然是utf-8)您可以随意使用
gcount
以外的标准函数,并且只将tellg
的结果保存到pos_type
。另外,请确保将separator传递到std::getline
(如果您不这样做,函数将给出异常std::bad_cast
)vxf3dgd46#
这个问题在Confused about C++'s std::wstring, UTF-16, UTF-8 and displaying strings in a windows GUI中得到了解决。总之,wstring基于UCS-2标准,这是UTF-16的前身。这是一个严格的两字节标准。我相信这涵盖了阿拉伯语。
5vf7fwbs7#
这有点生涩,但是将文件读取为普通的旧字节,然后将字节缓冲区转换为wchar_t*,怎么样?
类似于: