【问题标题】:Reading in Russian characters (Unicode) using a basic_ifstream<wchar_t>使用 basic_ifstream<wchar_t> 读取俄语字符 (Unicode)
【发布时间】:2010-03-17 16:57:08
【问题描述】:

这甚至可能吗?我一直在尝试读取一个包含俄语的简单文件,但它显然不起作用。

我调用了 file.imbue(loc)(此时,loc 是正确的,Russian_Russia.1251)。 buf 的类型为 basic_string

我使用 basic_ifstream 的原因是因为这是一个模板(从技术上讲,basic_ifstream,但在本例中是 T=wchar_t)。

这一切都与英文字符完美配合......

while (file >> ch)
{
    if(isalnum(ch, loc))
    {
        buf += ch;
    }
    else if(!buf.empty())
    {
        // Do stuff with buf.
        buf.clear();
    }
}

我不明白为什么我在阅读俄语字符时会收到垃圾。 (例如,如果文件包含 хеы хеы хеы,我会得到“яюE”、5(正方形)、K(正方形)等...

【问题讨论】:

  • 哦,C++ 中可爱的有问题的流 :) 也许这可以给你一个提示:stackoverflow.com/questions/1509277/…
  • 那么真的没有办法允许使用模板化流吗?在我看来,这似乎太复杂了。根本没有办法让流读取特定类型的字符?
  • 首先,“хеы хеы хеы”绝对不是俄语(尽管其中包含俄语字符)。然后,您能否使您的示例“完整”并提供指向示例文件的链接(在这种情况下,我很乐意为您提供帮助)。
  • 啊,NU UDACHI TOGDA,然后:))

标签: c++ locale ifstream


【解决方案1】:

代码页 1251 不适用于 Unicode —— 如果没有记错的话,它适用于 8859-5。不幸的是,您的 iostream 实现可能不支持“开箱即用”的 UTF-16。这有点奇怪,因为这样做只会涉及通过未更改的数据,但大多数人仍然不支持它。对于它的价值,至少如果我没记错的话,C++ 0x 应该添加这个。

【讨论】:

  • 那么,std::basic_ifstream 就不能完成吗?那它为什么存在呢?原谅我的问题的性质,我根本看不到使用流读取多字节字符的方法,并且一旦读取它们就不会是垃圾,除非您专门为每种类型编写代码多字节编码 - 这完全违背了模板的意义。
  • @Mark:这里的重点是您的输入不是 Unicode。您的实现是否需要 Unicode?​​span>
  • 我不太确定你的意思 - 我只知道文件将是 ASCII 或 Unicode(并且应该在编译时选择是否使用宽或窄字符 - 使用模板)。
  • basic_[io]stream 可以做到,但大多数实现都假设外部编码类似于 ISO 8859-x 或 shift JIS 而不是 Unicode。尽管他们并没有真正计划这样做,但可以使他们以 UTF-8 编码的 Unicode 读/写文件。让它与 UTF-16 或 UTF-32/UCS-4 一起工作会更加困难。鉴于您对每种编码都进行了不同的转换,因此在某些时候您需要为每种编码使用唯一的代码。该模板减少了其他地方不必要的重复。
【解决方案2】:

仍有许多 STL 实现没有可以处理 Unicode 编码的 std::codecvt。它们的 wchar_t 模板流将默认为系统代码页,即使它们以其他方式启用了 Unicode,例如文件名。如果文件实际上包含 UTF-8,它们会产生垃圾。也许this will help

【讨论】:

    【解决方案3】:

    默认情况下,Iostreams 假定磁盘上的任何数据都是非 unicode 格式,以便与不处理 unicode 的现有程序兼容。 C++0x 将通过允许原生 unicode 支持来解决这个问题,但此时 iostreams 使用std::codecvt&lt;wchar_t, char, mbstate_t&gt; 将普通字符数据转换为宽字符。见 cplusplus.com 的description of std::codecvt

    如果你想在 iostreams 中使用 unicode,你需要指定一个格式为 std::codecvt&lt;wchar_t, wchar_t, mbstate_t&gt; 的 codecvt facet,它只是通过数据不变。

    【讨论】:

    • 您只需将 facet 传递给 basic_istream::use_facet,就像使用任何其他 facet 一样。
    • 我不确定它是否存在...也许我误解了 facet 的工作原理,但我不明白你如何将一个传递给 use_facet,因为我认为 use_facet 没有定义对于 basic_ifstream。我可能是错的......
    • 对不起——我对这些东西不是很熟悉:(我想你要找的方法是std::basic_ifstream&lt;t&gt;::imbue
    【解决方案4】:

    我不确定,但你可以尝试调用 setlocale(LC_CTYPE, "");

    【讨论】:

    • Err.. 不,无论如何这是默认语言环境。
    猜你喜欢
    • 2012-04-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-12
    • 2015-04-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-19
    相关资源
    最近更新 更多