Я нахожусь в процессе исправления большого кроссплатформенного приложения с открытым исходным кодом, чтобы оно могло обрабатывать пути к файлам, содержащие не-ANSI символы в Windows.
Обновление:
Основываясь на полученных мной ответах и комментариях (спасибо!), Я чувствую, что должен уточнить некоторые моменты:
Я не могу изменить код десятков сторонних библиотек для использования std::wchar_t
. Это просто не вариант. Решение должно работать с обычными std::fopen()
, std::ifstream
, et c.
Решение, которое я обрисовал в общих чертах ниже, работает на 99%, , по крайней мере, на система, которую я разрабатываю на (Windows 10 версия 1909, сборка 18363.535). Я еще не тестировал ни в одной другой системе.
Единственная оставшаяся проблема, , по крайней мере, в моей системе , это в основном форматирование чисел, и я надеюсь, что замена фасета std::numpunct
делает трюк (но я пока не преуспел).
Мое текущее решение включает в себя:
Установка C языковой стандарт .UTF-8
для категории LC_CTYPE
в Windows (для всех остальных категорий устанавливается языковой стандарт C
в соответствии с требованиями приложения):
// Required by the application.
std::setlocale(LC_ALL, "C");
// On Windows, we want std::fopen() and other functions dealing with strings
// and file paths to accept narrow-character strings encoded in UTF-8.
#ifdef _WIN32
{
#ifndef NDEBUG
char* new_ctype_locale =
#endif
std::setlocale(LC_CTYPE, ".UTF-8");
assert(new_ctype_locale != nullptr);
}
#endif
Настройка boost::filesystem::path
для использования языкового стандарта en_US.UTF-8
, чтобы он также мог работать с путями, содержащими символы, отличные от ANSI:
boost::filesystem::path::imbue(std::locale("en_US.UTF-8"));
Последний отсутствующий бит - это исправление файлового ввода-вывода использование потоков C ++, таких как
std::ifstream istream(filename);
Самое простое решение, вероятно, состоит в том, чтобы установить глобальный языковой стандарт C ++ в начале приложения:
std::locale::global(std::locale("en_US.UTF-8"));
Однако это приводит к неправильному форматированию чисел, например 1234,56 форматируется как 1234,56.
Существует ли локаль, которая просто определяет кодировку UTF-8, не мешая с форматированием чисел (или другими вещами)?
В основном я ищу язык C.UTF-8
, но, похоже, его нет на Windows.
Обновление: я полагаю, что одним из решений будет сброс некоторых (большинство? все?) аспектов локали, но мне трудно найти информацию о том, как это сделать.