如何将文件读入wstring?

问题描述 投票:0回答:1

我正在尝试使用 wifstream 打开文件:

#include <sstream>
#include <fstream>

wstring readFile(const char* filename)
{
    wifstream wif(filename);
    wstringstream wss;
    wss << wif.rdbuf();
    return wss.str();
}

它正在读取包含英文和俄文符号的文件并将文本放入wstring中。

然后,我尝试将所有这些打印到控制台中,所有俄语符号都被替换为另一个符号。英文符号正确。

我发现,替换符号的所有字符代码(如\u...)都是正确的。而且它们不在 ASCII 表中,例如 å - U+00E5 (en.wikipedia.org/wiki/List_of_Unicode_characters)

我认为将文件解码为 utf-8 时存在问题。

c++ unicode ifstream wifstream
1个回答
0
投票

无需任何额外设置,

wifstream
将使用
C
语言环境,这可能不是您想要的。

有多种可能的解决方案:


1.使用默认区域设置

要使用默认区域设置读取文件,请将

std::wifstream
std::locale("")
结合使用。这就是大多数 Linux 程序的工作方式。

示例:

#include <fstream>
#include <iostream>
#include <ranges>

int main()
{
    std::wifstream stream("sample.txt");
    if (!stream)
    {
        std::cerr << "Failed to open file\n";
        return 1;
    }

    stream.imbue(std::locale(""));

    for (auto c : std::views::istream<wchar_t>(stream))
    {
        std::cout << std::hex << static_cast<int>(c) << std::endl;
    }

    if (stream.bad())
    {
        std::cerr << "Failed to extract character\n";
    }
}

大多数 Linux 发行版默认使用 UTF-8。 Windows 也可以配置为使用 UTF-8,尽管我相信这不是默认设置。


2.使用 UTF-8 语言环境

虽然没有真正完全可移植的方法来执行此操作,但以下内容似乎在 Windows 和 Linux 上都适用(只要

en_US.utf-8
语言环境可用):

stream.imbue(std::locale("en_US.utf-8"));

3.使用已弃用 (C++17)/已删除 (C++26)
codecvt_utf8_utf16

警告:请勿在生产中使用

<codecvt>
中的内容存在与错误处理相关的问题,并将从标准中删除。我也不相信他们能够正确处理格式错误(或潜在恶意)的输入。

stream.imbue(std::locale(std::locale::classic(), new std::codecvt_utf8_utf16<wchar_t>));

4.使用图书馆

对于不能简单依赖默认语言环境的生产代码来说,这实际上是最佳选择。


那么您应该选择哪种方法呢?这取决于:

  • 如果您只想进行一些快速测试,选项#2 可能是最简单的。只是不要在生产中使用它;
  • 如果您的程序使用默认语言环境是可以接受的(或者甚至是理想的,如果您的目标是 Linux),请使用选项#1;
  • 否则,请使用#4。
© www.soinside.com 2019 - 2024. All rights reserved.