Я хочу написать приложение для изучения языка для себя, используя Visual Studio 2017, C ++ и WindowsAPI (ранее известный как Win32). Операционная система является последней инсайдерской сборкой Windows 10, и обратная совместимость не является проблемой. Поскольку я предполагаю, что английский язык является родным языком пользователя, а язык, которым я в данный момент интересуюсь, является еще одним европейским языком, ASCII может быть достаточно. Но я хочу сделать это на будущее (больше экзотических языков), а также хочу попробовать свои силы в UTF-32. Ранее я использовал как UTF-8, так и UTF-16, хотя у меня больше опыта с последующим.
Благодаря std::basic_string
было легко понять, как получить строку UTF-32:
typedef std::basic_string<char32_t> stringUTF32
Поскольку я использую WinAPI для всего персонала графического интерфейса, мне нужно сделать некоторое преобразование между UTF-32 и UTF-16.
Теперь о моей проблеме: поскольку UTF-32 не используется широко из-за его неэффективности, в Интернете практически нет материалов об этом. Чтобы избежать ненужных преобразований, я хочу сохранить свои словарные списки и другие данные как UTF-32 (для всех сторонников / евангелистов UTF-8 альтернативой будет UTF-16). Проблема в том, что я не могу найти, как писать и открывать файлы в UTF-32.
Итак, мой вопрос: как писать / открывать файлы в UTF-32? Я бы предпочел, чтобы сторонние библиотеки не требовались, если они не являются частью Windows или обычно поставляются с этой ОС.
Если у тебя есть char32_t
последовательность, вы можете записать его в файл, используя std::basic_ofstream<char32_t>
(который я буду называть u32_ofstream
, но этот typedef не существует). Это работает так же, как std::ofstream
кроме того что пишет char32_t
с вместо char
s. Но есть ограничения.
Большинство стандартных типов библиотек, которые имеют operator<<
Перегрузка зависит от типа символа. Таким образом, они будут работать с u32_ofstream
просто хорошо. Проблема, с которой вы столкнетесь, для пользователь типы. Они почти всегда предполагают, что вы пишете char
и, таким образом, определяются как ostream &operator<<(ostream &os, ...);
, Такой поток вывода не может работать с u32_ofstream
без конверсионного слоя.
Но большая проблема, с которой вы столкнетесь, — это проблемы с порядком байтов. u32_ofstream
напишет char32_t
как родной порядок байтов вашей платформы. Если ваше приложение читает их обратно через u32_ifstream
, Все в порядке. Но если другие приложения читают их, или если ваше приложение должно читать что-то, написанное в UTF-32 кем-то другим, это становится проблемой.
Типичным решением является использование «метки порядка байтов» в качестве первого символа файла. Unicode даже имеет определенную кодовую точку, выделенную для этого: \U0000FEFF
,
То, как работает спецификация, выглядит следующим образом. При написании файла вы пишете спецификацию перед любыми другими кодовыми точками.
При чтении файла с неизвестной кодировкой вы читаете первую кодовую точку как обычно. Если в вашей исходной кодировке она совпадает с спецификацией, остальную часть файла вы можете прочитать как обычно. Если это не так, то вам нужно прочитать файл и выполнить обратное преобразование, прежде чем вы сможете его обработать. Этот процесс будет выглядеть примерно так:
constexpr char32_t native_bom = U'\U0000FEFF';
u32_ifstream is(...);
char32_t bom;
is >> bom;
if(native_bom == bom)
{
process_stream(is);
}
else
{
basic_stringstream<char32_t> char_stream
//Load the rest of `is` and endian-convert it into `char_stream`.
process_stream(char_stream);
}
Меня сейчас интересует другой европейский язык, поэтому ASCII может быть достаточно
Даже на простом английском. Вы знаете, как Microsoft Word создает «фигурные кавычки»? Это не символы ASCII. Все эти письма с акцентами и умлауты, например. Французский или английский не являются символами ASCII.
Я хочу это на будущее
UTF-8, UTF-16 и UTF-32 могут кодировать каждую кодовую точку Unicode. Они все на будущее. UTF-32 не имеет преимущества перед двумя другими.
Также для проверки в будущем: я уверен, что некоторые сценарии используют символы (технический термин — «кластеры графем»), состоящие из более чем одного кода. Беглый поиск Игра с персонажами деванагари.
Недостатком UTF-32 является поддержка других инструментов. Блокнот не открывает ваши файлы. Вне сравнения не буду. Код Visual Studio… нет. Visual Studio будет, но она не позволит вам создавать такие файлы.
И Win32 API: у него есть функция MultiByteToWideChar который может конвертировать UTF-8 в UTF-16 (который необходимо передать во все вызовы Win32), но он не принимает UTF-32.
Поэтому мой честный ответ на этот вопрос: не. В противном случае следуйте ответу Николь.