如何wstring
在 Windows 平台上将 Unicode (UTF-8) 文件读入 (s)?
6 回答
借助 C++11 支持,您可以使用std::codecvt_utf8 facet ,它封装了 UTF-8 编码字节字符串和 UCS2 或 UCS4 字符串之间的转换,可用于读取和写入 UTF-8 文件,包括文本和二进制文件.
为了使用facet,您通常会创建locale 对象 ,该对象将特定于文化的信息封装为一组共同定义特定本地化环境的 facet。一旦你有了一个语言环境对象,你就可以用它来填充你的流缓冲区:
#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");
或者,您可以在使用字符串流之前设置全局 C++ 语言环境,这会导致对std::locale
默认构造函数的所有未来调用返回全局 C++ 语言环境的副本(然后您不需要显式地用它来填充流缓冲区):
std::locale::global(std::locale(std::locale::empty(), new std::codecvt_utf8<wchar_t>));
根据@Hans Passant 的评论,最简单的方法是使用_wfopen_s。使用 mode 打开文件rt, ccs=UTF-8
。
这是另一个至少适用于 VC++ 2010 的纯 C++ 解决方案:
#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()
也可以工作)和构造函数的wchar_t*
重载之外basic_ifstream
,这甚至应该非常符合标准(当然,“标准”意味着 C++0x)。
这是仅适用于 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");
请注意,整个文件已加载到内存中,因此您可能不想将其用于非常大的文件。
#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();
}
这个问题在Confused about C++'s std::wstring, UTF-16, UTF-8 and display strings in a windows GUI 中得到解决。总之,wstring 基于 UCS-2 标准,它是 UTF-16 的前身。这是一个严格的两字节标准。我相信这涵盖了阿拉伯语。
这有点原始,但是如何将文件作为普通的旧字节读取然后将字节缓冲区转换为 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;
}