【问题标题】:g++ unicode character ifstreamg ++ unicode字符ifstream
【发布时间】:2013-01-14 18:35:18
【问题描述】:

这是一个关于文本输入文件中的 unicode 字符的问题。 This discussion was close but not quite the answer。用 VS2008 编译并在 Windows 上执行这些字符在读取时被识别(可能表示为不同的符号但已读取) - 用 g++ 编译并在 linux 上执行它们显示为空白。

‚ ƒ „ … † ‡ ˆ ‰ Š ‹ Œ Ž ‘ ’ “ ” • – — ˜ ™ š › œ ž Ÿ

其余的 Unicode 符号似乎工作正常,我没有检查它们,但发现这组不起作用。

问题: (1) 为什么? (2) 有解决办法吗?

void Lexicon::buildMapFromFile(string filename )  //map
{
    ifstream file;
    file.open(filename.c_str(), ifstream::binary);
    string wow, mem, key;
    unsigned int x = 0;

    while(true) {
        getline(file, wow);
        cout << wow << endl;
        if (file.fail()) break; //boilerplate check for error
        while (x < wow.length() ) {
            if (wow[x] == ',') { //look for csv deliniator
                key = mem;
                mem.clear();
                x++; //step over ','
            } else 
                mem += wow[x++];
        }

        //cout << mem << " code " << key << " is " << (key[0] - '€') << " from €" << endl;

        cout << "enter 1 to continue: ";
        while (true) {
            int choice = GetInteger();
            if (choice == 1) break;
        }

        list_map0[key] = mem; //char to string
        list_map1[mem] = key; //string to char
        mem.clear(); //reset memory
        x = 0;//reset index
    }
    //printf("%d\n", list_map0.size());
    file.close();
}

从 csv 文件中读取 unicode 符号并解析为 unicode 符号和关联的字符串。最初我虽然代码中存在错误,但在 this post the review 中发现它很好,我按照问题处理字符。

测试是cout &lt;&lt; wow &lt;&lt; endl;

【问题讨论】:

  • “没有可发布的代码”...“用 g++ 编译”。请消除矛盾。
  • 好的,在上下文中没有理由发布代码,虽然从技术上讲你是正确的,有代码要发布 - 对不起我糟糕的语法语义
  • Windows 和 Linux 也一样吗?大不同!
  • 我知道有人会问问题是什么 - 抱歉。是的,#Bo Persson 它是 windows 和 linux

标签: c++ linux unicode g++ ifstream


【解决方案1】:

您显示的字符都是来自 Windows 代码页 1252 的字符,这些字符在 ISO-8859 1 编码中不存在。这两种编码很相似,所以经常混淆。

如果输入是 CP1252 并且您正在阅读它,就像它是 ISO-8859 1 一样,那么这些字符将被读取为控制字符,并且不会像正常的可见字符那样表现。


有很多可能是您做错了事情导致了这种情况,但您必须发布更多详细信息才能确定是哪一个。更完整的答案需要了解您如何读取数据、如何在内部转换和存储数据、如何测试读取的数据以及输入数据和/或编码。


您显示的代码在读取数据时没有进行任何转换,打印数据的注释掉的代码是相同的;没有转换。这意味着打印您只是依赖输入数据的数据,以确保您运行程序的平台是正确的。这意味着,例如,如果您在 Windows 的控制台中运行程序,那么您的输入文件需要使用控制台的代码页*进行编码。

要解决问题,您可以;确保输入文件与您运行程序的特定控制台所需的编码匹配;或者指定输入编码,读取时转换为已知的内部编码,然后打印时转换为控制台编码。

* 如果不是,例如如果控制台是 cp437 而文件是 cp1252,那么您列出的字符将改为显示为:É æ Æ ô ö ò û ù ÿ Ö Ü ¢ £ ¥ ₧ ƒ á í ó ú ñ Ñ ª º ¿ ⌐ ¬ ½ ¼ ¡ « »

【讨论】:

  • #bames53 将详细信息添加到问题中
  • #bames53 我使用 unicode 字符来表示在本体上表示动作的字符串标记,请参阅 ICD9 和 masterformat。我在内部使用它,并在读取时从本体字符串转换为 uniformat char,并在写入时从 unicode c 转换回本体字符串。单个字符简化了很多。这里的软件开发人员被我的研究生解决方案逗乐了,但告诉我使用带有整数的整数向量而不是 unicode 字符来实现相同的功能和改进的行为。但是,我想了解为什么它不起作用,因为它在概念上起作用并且实际上在 win 中起作用。
  • #bames53 谢谢您,在查看了 ISO8859-1 和 Windows-1252 wiki 页面上的表格后,您的解释现在很清楚了。既然你知道这个话题,我在 win 中遇到了 À Á Â Ã 显示为 Á 的问题(后续字符字母组的问题相同) - 我没有在 linux 中检查过相同的问题。
【解决方案2】:

您的问题陈述没有详细说明您的 g++ 平台,但从您的标签看来,您正在 linux 上编译相同的代码。

Windows 和 linux 都启用了 unicode。因此,如果您在 windows/vs-2008 中的代码具有 wstring 类,那么您必须在 linux/g++ 上将其更改回字符串。如果你在 linux 中使用 wstring,它不会以同样的方式工作。

【讨论】:

  • #Sandeep 平台是 windows 和 linux - 我不确定你对他 wstring 类的意思,我使用了 #include
【解决方案3】:

C++ 代码中的 Unicode 处理并不简单,它取决于实现(您已经看到 VS2008 和 g++ 之间的输出变化)。此外,Unicode 可以通过不同的字符编码(如 UTF-8 和 UTF-16)来实现。

有一篇启发性的文章in this page。它讨论了基于 STL 的软件的 Unicode 转换。对于文本 i/o,主要武器是 codecvt,这是一个库函数,可用于在不同字符编码系统之间转换字符串。

【讨论】:

  • #Davide Aversa 我阅读了您提供的链接,但 1)我使用的实现要简单得多,2)我的知识比那篇文章低
猜你喜欢
  • 1970-01-01
  • 2012-09-23
  • 2011-02-10
  • 1970-01-01
  • 2017-11-19
  • 1970-01-01
  • 2013-10-17
  • 2011-03-20
相关资源
最近更新 更多