如何在cygwin下使用gcc设置std::locale?

发布于 2024-12-11 07:38:20 字数 1729 浏览 0 评论 0原文

我正在尝试编写一个简单的程序来枚举磁盘上的文件,但我陷入了伟大的 UTF 前沿。

我正在使用 boost::recursive_directory_iterator 来枚举文件。这很好用,但 Windows 设置为“加拿大法语”,并且许多文件和目录都有法语字符(如 é、è、ç)。这些文件名未正确显示在屏幕上,我正在使用 wcout。我看到一个“▒”而不是锐角字符。即使 boost::filesystem::ifstream 也无法打开这些文件。

我尝试添加“std::locale::global(std::locale(""))”,但起初只抛出异常。我发现当执行程序时 LANG 设置为“”时,前一个命令不再抛出任何异常,但它只设置“C”语言环境,而不是操作系统使用的语言环境(我希望是“ fr_CA.UTF-8”或“fr_CA.ISO8859-1”)。 LANG 的任何其他值都会使异常恢复...

必须做什么才能让 cygwin gcc 程序在 i18n 世界中可用?

我写这个是为了测试各种区域设置 ID:

#include <iomanip>
#include <iostream>
#include <locale>

using namespace std;

void tryLocale(string ID)
{
    try{
        cout << "Trying " << std::setw(18) << std::left << "\"" + ID + "\" ";

        std::locale Loc(ID.c_str());
        cout << "OK (" << Loc.name() << ")" << endl;
    }catch(...){
        cout << "FAIL" << endl;
    }
}

const char *Locales[] = { "", "fr", "fr_CA", "fr_CA.UTF-8", "fr_CA.ISO8859-1", "C", 0};

int main()
{
    cout << "Classic = " << std::locale::classic().name() << endl << endl;

    int i = 0;
    do
    { tryLocale(Locales[i]);
    } while(Locales[++i]);

    return 0;
}

这给了我这个输出(没有任何 LANG 或 LC_ALL):

Classic = C

Trying ""                FAIL
Trying "fr"              FAIL
Trying "fr_CA"           FAIL
Trying "fr_CA.UTF-8"     FAIL
Trying "fr_CA.ISO8859-1" FAIL

将 LANG 设置为“”,第一个“尝试”变成

Trying ""                OK (C)

抛出的异常打印:

terminate called after throwing an instance of 'std::runtime_error'
  what():  locale::facet::_S_create_c_locale name not valid

I'm trying to make a simple program to enumerate the files on my disks, but I'm stuck at the great UTF frontier.

I'm using boost::recursive_directory_iterator to enumerate the files. That's works great, but Windows is set to "french canada" and many files and directories have french characters (likes é, è, ç). These filenames are not displayed correctly on the screen and I'm using wcout. I see a '▒' instead of the acute chars. Even boost::filesystem::ifstream is unable to open these files.

I tried to add "std::locale::global(std::locale(""))", but at first that only thrown an exception. I have found that when LANG is set to "" while executing the program, the previous command does not throw any more, but it only set the "C" locale instead of being the one use by the OS (which I expect to be "fr_CA.UTF-8" or "fr_CA.ISO8859-1"). Any other value for LANG bring the exception back...

What must be done to have a cygwin gcc program usable in an i18n world?

I have write this to test various locale ID:

#include <iomanip>
#include <iostream>
#include <locale>

using namespace std;

void tryLocale(string ID)
{
    try{
        cout << "Trying " << std::setw(18) << std::left << "\"" + ID + "\" ";

        std::locale Loc(ID.c_str());
        cout << "OK (" << Loc.name() << ")" << endl;
    }catch(...){
        cout << "FAIL" << endl;
    }
}

const char *Locales[] = { "", "fr", "fr_CA", "fr_CA.UTF-8", "fr_CA.ISO8859-1", "C", 0};

int main()
{
    cout << "Classic = " << std::locale::classic().name() << endl << endl;

    int i = 0;
    do
    { tryLocale(Locales[i]);
    } while(Locales[++i]);

    return 0;
}

And that gives me this output (without any LANG or LC_ALL):

Classic = C

Trying ""                FAIL
Trying "fr"              FAIL
Trying "fr_CA"           FAIL
Trying "fr_CA.UTF-8"     FAIL
Trying "fr_CA.ISO8859-1" FAIL

With LANG set to "", the first "trying" becomes

Trying ""                OK (C)

The exception thrown print this:

terminate called after throwing an instance of 'std::runtime_error'
  what():  locale::facet::_S_create_c_locale name not valid

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文