使用 std::wifstream 读取带有特殊字符的 unicode 文件
Posted
技术标签:
【中文标题】使用 std::wifstream 读取带有特殊字符的 unicode 文件【英文标题】:Read unicode file with special characters using std::wifstream 【发布时间】:2014-09-30 13:12:27 【问题描述】:在Linux环境下,我有一段读取unicode文件的代码,类似如下图。
但是,无法正确处理特殊字符(如丹麦字母 æ、ø 和 å)。对于“abcæøåabc”行,输出只是“abc”。使用调试器我可以看到wline
的内容也只有a\000b\000c\000
。
#include <fstream>
#include <string>
std::wifstream wif("myfile.txt");
if (wif.is_open())
//set proper position compared to byteorder
wif.seekg(2, std::ios::beg);
std::wstring wline;
while (wif.good())
std::getline(wif, wline);
if (!wif.eof())
std::wstring convert;
for (auto c : wline)
if (c != '\0')
convert += c;
wif.close();
谁能告诉我如何让它阅读整行?
感谢和问候
【问题讨论】:
对文件进行十六进制转储,它包含什么? 我得到了以下十六进制转储0000000: fffe 6100 6200 6300 e600 f800 e500 6100 ..a.b.c.......a. 0000010: 6200 6300 0d00 0a00 b.c.....
即使字符本身没有显示在上面的输出中,至少十六进制值似乎是正确的 - fffe
用于 utf-16-le 编码,@987654327 @ 代表 æ,f800
代表 ø,e500
代表 æ。
您需要使用带有 UTF-16LE 语言环境的imbue
来指示文件的格式。我试图为您找到相关指南,但找不到。
@MarkRansom: en.cppreference.com/w/cpp/locale/codecvt_utf16 显示了一个示例。
【参考方案1】:
您必须使用imbue()
方法告诉wifstream
该文件被编码为UTF-16,并让它为您消耗BOM。您不必手动通过 BOM 表 seekg()
。例如:
#include <fstream>
#include <string>
#include <locale>
#include <codecvt>
// open as a byte stream
std::wifstream wif("myfile.txt", std::ios::binary);
if (wif.is_open())
// apply BOM-sensitive UTF-16 facet
wif.imbue(std::locale(wif.getloc(), new std::codecvt_utf16<wchar_t, 0x10ffff, std::consume_header>));
std::wstring wline;
while (std::getline(wif, wline))
std::wstring convert;
for (auto c : wline)
if (c != L'\0')
convert += c;
wif.close();
【讨论】:
感谢您的反馈。不幸的是 codecvt_utf16 在我的系统上不可用。我没有读取文件的每一行,而是使用 fread() 。它有点麻烦而且不那么整洁,但它确实有效。您的解决方案将是首选解决方案,但正如我所说,这对我来说似乎不可能 您使用的是哪个编译器?您正在使用auto
,这是 C++11 的一项功能,而 codecvt_utf16
是 C++11 的一部分。您是否在代码中添加了#include <codecvt>
?
我在 Ubuntu 14.04 上使用 gcc4.9。我无法包含 codecvt
、codecvt_base
和codecvt_byname
<codecvt>
中的类在 C++17 中确实已被弃用,但目前还没有标准的替代品。我认为标准委员会正在推动人们使用外部 Unicode 库。以上是关于使用 std::wifstream 读取带有特殊字符的 unicode 文件的主要内容,如果未能解决你的问题,请参考以下文章