将Unicode UTF-8文件读入wstring

Abd*_*hed 37 c++ unicode file utf-8 wstring

如何wstring在Windows平台上读取(UTF-8)文件?

Lih*_*ihO 33

随着C++ 11的支持,你可以使用的std :: codecvt_utf8方面 它封装了一个UTF-8编码的字节串和UCS2或UCS4字符串之间的转换,并可以用来读取和写入UTF-8文件,文本和二进制.

为了使用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();
}
Run Code Online (Sandbox Code Playgroud)

可以像这样使用:

std::wstring wstr = readFile("a.txt");
Run Code Online (Sandbox Code Playgroud)

或者,您可以在使用字符串流之前设置全局C++语言环境,这会导致将来对std::locale默认构造函数的所有调用都返回全局C++语言环境的副本(您不需要使用它显式地为其添加流缓冲区):

std::locale::global(std::locale(std::locale::empty(), new std::codecvt_utf8<wchar_t>));
Run Code Online (Sandbox Code Playgroud)

  • 这个`new codecvt_utf8`是否需要相应的`delete`? (2认同)
  • 对于使用此答案的人,std::locale::empty() 在 clang 上存在问题:错误:'std::__1::locale' 中没有名为 'empty' 的成员。 (2认同)
  • 遗憾的是,codecvt 的所有有用部分在 C++20 中都已被弃用。 (2认同)

Phi*_*ipp 14

根据@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");
}
Run Code Online (Sandbox Code Playgroud)

除了locale::empty()(这里locale::global()可能也有效)和构造函数的wchar_t*重载之外basic_ifstream,这甚至应该是非常符合标准的(其中"标准"意味着C++ 0x,当然).

  • 你为什么不'删除转换器'? (5认同)

Ash*_*ain 6

这是仅适用于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;
}
Run Code Online (Sandbox Code Playgroud)

使用如下:

std::wstring mytext = LoadUtf8FileToString(L"C:\\MyUtf8File.txt");
Run Code Online (Sandbox Code Playgroud)

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

  • 不妨全程走:_wfopen(filename.c_str(),L"rt,ccs = UTF-8"); 转换现在是自动的. (3认同)

She*_* Yu 5

#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();
}
Run Code Online (Sandbox Code Playgroud)

  • 我最近有一些问题,但我现在已经解决了,我想分享我的解决方案来帮助其他人。 (3认同)

Tho*_*eod 0

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