Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/151.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 获取用户';boost::locale::conv中函数的代码页名称 手头的任务_C++_Windows_Utf 8_Codepages_Boost Locale - Fatal编程技术网

C++ 获取用户';boost::locale::conv中函数的代码页名称 手头的任务

C++ 获取用户';boost::locale::conv中函数的代码页名称 手头的任务,c++,windows,utf-8,codepages,boost-locale,C++,Windows,Utf 8,Codepages,Boost Locale,我正在从Windows上的UTF-8编码的XML解析文件名。我需要将该文件名传递给一个我无法更改的函数。它在内部使用不支持Unicode字符串的字符串 当前方法 我目前的方法是将文件名转换为用户的字符集,希望文件名可以用这种编码表示。然后,我使用boost::locale::conv::from\u utf()从utf-8转换,并使用boost::locale::util::get\u system\u locale()获取当前区域设置的名称 生活是美好的? 我在一个使用代码页的德国系统上,因此

我正在从Windows上的UTF-8编码的XML解析文件名。我需要将该文件名传递给一个我无法更改的函数。它在内部使用不支持Unicode字符串的字符串

当前方法 我目前的方法是将文件名转换为用户的字符集,希望文件名可以用这种编码表示。然后,我使用
boost::locale::conv::from\u utf()
从utf-8转换,并使用
boost::locale::util::get\u system\u locale()
获取当前区域设置的名称

生活是美好的?

我在一个使用代码页的德国系统上,因此
get_system_locale()
正确地生成de_de.windows-1252。如果我用一个包含umlaut的文件名测试该方法,那么一切都会按预期工作

问题 只是为了确保我使用的是使用代码页的乌克兰语。在文件名中使用一些西里尔字母,我的方法失败了。原因是
get_system_locale()
仍然会生成de_de.windows-1252,这现在是不正确的

另一方面,正确的结果是,德国地区为1252,乌克兰地区为1251。我还知道Boost.Locale可以转换为给定的语言环境,因为这个小测试程序可以像我预期的那样工作:

#include <boost/locale.hpp>
#include <iostream>
#include <string>
#include <windows.h>

int main()
{
    std::cout << "Codepage: " << GetACP() << std::endl;
    std::cout << "Boost.Locale: " << boost::locale::util::get_system_locale() << std::endl;

    namespace blc = boost::locale::conv;
    // Cyrillic small letter zhe -> \xe6 (ш on 1251, æ on 1252)
    std::string const test1251 = blc::from_utf(std::string("\xd0\xb6"), "windows-1251");
    std::cout << "1251: " << static_cast<int>(test1251.front()) << std::endl;
    // Latin small letter sharp s -> \xdf (Я on 1251, ß on 1252)
    auto const test1252 = blc::from_utf(std::string("\xc3\x9f"), "windows-1252");
    std::cout << "1252: " << static_cast<int>(test1252.front()) << std::endl;

}
#包括
#包括
#包括
#包括
int main()
{

标准::coutANSI已被弃用,因此不必为此费心

Windows使用UTF16,您必须使用
MultiByteToWideChar
将UTF8转换为UTF16。此转换是安全的

std::wstring getU16(const std::string &str)
{
    if (str.empty()) return std::wstring();
    int sz = MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), 0, 0);
    std::wstring res(sz, 0);
    MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), &res[0], sz);
    return res;
}
然后使用
\u wfsopen
(从您提供的链接)打开具有UTF16名称的文件

int main()
{
    //UTF8 source:
    std::string filename_u8;

    //This line works in VS2015 only
    //For older version comment out the next line, obtain UTF8 from another source
    filename_u8 = u8"c:\\test\\__ελληνικά.txt";

    //convert to UTF16
    std::wstring filename_utf16 = getU16(filename_u8);

    FILE *file = NULL;
    _wfopen_s(&file, filename_utf16.c_str(), L"w");
    if (file)
    {
        //Add BOM, optional...

        //Write the file name in to file, for testing...
        fwrite(filename_u8.data(), 1, filename_u8.length(), file);

        fclose(file);
    }
    else
    {
        cout << "access denined, or folder doesn't exits...
    }

    return 0;
}

巴马克的方法是最好的方法

要清除区域设置内容,该过程始终以“C”区域设置开始。您可以使用将区域设置设置为系统默认值或任意区域设置

#include <clocale>

// Get the current locale
setlocale(LC_ALL,NULL);

// Set locale to system default
setlocale(LC_ALL,"");

// Set locale to German
setlocale(LC_ALL,"de-DE");
#包括
//获取当前区域设置
setlocale(LC_ALL,NULL);
//将区域设置设置为系统默认设置
setlocale(LC_ALL,“”);
//将区域设置为德语
设置语言环境(LC_ALL,“de de”);

谢谢您的回答。问题是转换函数的区域设置重载与标准区域设置不兼容。字符集as string重载与这些区域设置的名称一起失败,即使在剥离语言区域部分时也是如此。您提到的转换函数仍然是boost函数?不幸的是,我没有我对boost locale函数有很多经验。我过去在Windows上使用的从一种编码到另一种编码的技巧是使用宽字符,然后返回到不同的编码。是的,仍然是boost函数。我猜它们在内部也是这样做的,关键问题是MS uint代码页ID如何映射到boost代码页字符串。假设我无法更改函数,这很遗憾没有帮助。但这仍然很有希望,因为接口太稳定,无法更改,但函数只需要努力。谢谢,我将尝试一下。您描述的问题相当复杂,这是Unicode在第一个pla中发明的部分原因ce。我添加了一个函数,以从UTF8获得ANSI,这是Iverelo建议的。另请参阅关于系统语言的这一部分,我不确定这是否有帮助。幸运的是,我成功地采纳了您的第一个建议。它允许保留稳定的接口,但更改了内部结构。我使用了
boost::locale::conv::utf_to_utf()
而不是您的
getU()
。不幸的是,实际问题仍然没有答案。但是您现在提供了一种绕过boost限制的方法,因此我接受这个答案。
#include <clocale>

// Get the current locale
setlocale(LC_ALL,NULL);

// Set locale to system default
setlocale(LC_ALL,"");

// Set locale to German
setlocale(LC_ALL,"de-DE");