【问题标题】:Can't read cyrillic from .txt file无法从 .txt 文件中读取西里尔字母
【发布时间】:2021-06-10 12:33:57
【问题描述】:

我想从 .txt 文件中读取这个西里尔文字:аааааааааааа

std::wstring str;
std::wifstream in(path);
std::getline(in, str);
in.close();

但是str 的内容是:аааааааааааа(文件编码 - UTF-8)(在调试中观察到的字符串内容,而不是在控制台中)

我尝试将文件编码更改为 UTF-16(LE 和 BE),有:ÿþ000000000000 和 þÿ000000000000

另外,我找到了this solution,但正如你所见,它没有帮助。

【问题讨论】:

  • wstring 和 wifstream 用于 wchar_t,它不需要编码,因此它不是 UTF-16 或 UTF-32。 (它可以是其中一种编码,但这不是数据类型所要求的。)由于您的文件是 UTF-8,您可能应该使用基于char 的string 和ifstream。 (和wchar_t 一样,char 类型也不需要编码。)(我没有投反对票。)
  • @Eljay string 和 ifstream 有同样的问题。 string和wstring之间的唯一区别是,如果我直接将西里尔文文本分配给程序中的变量,string同样废话,当wstring正确存储原始文本时

标签: c++ string unicode


【解决方案1】:

在 Windows 中,您必须以二进制文件打开文件,然后应用 UTF16 方面,否则系统将采用默认代码页。请参见下面的示例。

请注意,使用 UTF8 存储数据是很常见的,即使在 Windows 应用程序中也是如此。您的 Windows 程序要求 API 使用 UTF16,因此您可以以 UTF8 读取/写入文件,然后来回转换为 UTF16

#define _SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING
//silence codecvt warnings

std::wstring str;
std::wifstream in(path, std::ios::binary);
in.imbue(std::locale(in.getloc(), 
    new std::codecvt_utf16<wchar_t, 0x10ffff, std::little_endian>));
std::getline(in, str);
in.close();

您也可以使用pubsetbuf 来避免codecvt 警告:

std::wifstream in(path, std::ios::binary);
wchar_t wbuf[128] = { 0 };
in.rdbuf()->pubsetbuf(wbuf, 128);

//BOM check
wchar_t bom{};
in.read(&bom, 1);
if(bom == 0xfeff)
    std::cout << "UTF16-LE\n";

//read file
std::wstring str;
std::getline(in, str);
in.close();

【讨论】:

  • 是的,它的工作,它还需要将文件保存为 UTF-16LE。但我还有一个问题。当我试图找到解决方案时,我已经看到了codevect,有点不同,但现在不是这样了。我读到 codevct 已被弃用且不完全安全。这可能有问题吗?在 C++ 的上下文中不推荐使用它是什么意思?感谢您的帮助和回答!
  • 此代码在 Linux 和 Windows 中的处理方式不同。 wchar_t 在 Linux 和 Windows 中也不同。这导致不同的代码。 “不推荐使用”的意思是“将来可能不支持此代码,请使用较新的代码......”但在这种情况下,还没有替代 codecvt。最好的选择是使用 UTF8 来存储数据。您的数据将与 Linux 和基于 Web 的数据兼容...只需使用 MultiByteToWideChar(CP_UTF8, ...) 将 UTF8 转换为 UTF16。 Visual Studio 支持 std::fstream 的宽字符文件名,因此您可以编写 std::fstream(L"filename.txt")
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-09-10
  • 2017-10-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多