将Unicode UTF-8文件读入wstring

时间:2011-01-23 18:04:37

标签: c++ file unicode utf-8 wstring

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

6 个答案:

答案 0 :(得分:29)

在C ++ 11支持下,您可以使用std::codecvt_utf8 facet 封装UTF-8编码字节字符串与UCS2或UCS4字符串之间的转换,可以使用读写UTF-8文件,包括文本和二进制文件。

为了使用facet,您通常会创建locale object ,将特定于文化的信息封装为一组共同定义特定本地化环境的方面。一旦有了语言环境对象,你可以用它来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>));

答案 1 :(得分: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");
}

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

答案 2 :(得分:5)

以下是仅适用于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");

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

答案 3 :(得分:2)

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

答案 4 :(得分:0)

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

答案 5 :(得分:-3)

这有点原始,但如何以普通的旧字节读取文件然后将字节缓冲区转换为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;
}