c++ 将Unicode UTF-8文件读入wstring

f45qwnt8  于 2023-04-13  发布在  其他
关注(0)|答案(7)|浏览(204)

如何在Windows平台上将Unicode(UTF-8)文件读入wstring(s)?

sg24os4d

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::global(std::locale(std::locale::empty(), new std::codecvt_utf8<wchar_t>));
vwoqyblh

vwoqyblh2#

根据@Hans Passant的评论,最简单的方法是使用_wfopen_s。以rt, ccs=UTF-8模式打开文件。
下面是另一个纯C解决方案,至少可以在VC 2010中使用:

#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)。

ghhaqwfi

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");

请注意,整个文件将加载到内存中,因此您可能不希望将其用于非常大的文件。

7ivaypg9

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();
}
8fsztsew

8fsztsew5#

最近处理了所有的编码,用这种方式解决。最好使用std::u32string,因为它在所有平台上都有稳定的大小,并且大多数字体都使用utf-32格式。(文件应该仍然是utf-8)

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

vxf3dgd4

vxf3dgd46#

这个问题在Confused about C++'s std::wstring, UTF-16, UTF-8 and displaying strings in a windows GUI中得到了解决。总之,wstring基于UCS-2标准,这是UTF-16的前身。这是一个严格的两字节标准。我相信这涵盖了阿拉伯语。

5vf7fwbs

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;
}

相关问题