Как вы пишете код, безопасный для UTF-8?

У нас есть набор приложений, которые были разработаны для набора символов ASCII. Теперь мы пытаемся установить его в Исландии и сталкиваемся с проблемами, когда исландские персонажи напортачиваются.

Мы работаем над нашими проблемами, но мне было интересно: есть ли там хороший "справочник" для написания кода на С++, который предназначен для 8-битных символов и который будет работать правильно, когда ему будут переданы данные UTF-8

Я не могу ожидать, что каждый прочитает весь стандарт Unicode, но если есть что-то более доступное, я бы хотел поделиться им с командой, чтобы мы снова не сталкивались с этими проблемами.

Повторная запись всех приложений для использования wchar_t или какого-либо другого строкового представления в настоящее время невозможна. Я также отмечу, что эти приложения обмениваются данными по сетям с серверами и устройствами, использующими 8-битные символы, поэтому, даже если бы мы сделали Unicode внутри, у нас все еще были бы проблемы с переводом на границах. По большей части эти приложения просто передают данные; они не "обрабатывают" текст каким-либо образом, кроме копирования его с места на место.

В качестве операционных систем используются Windows и Linux. Мы используем std::string и простые строки C. (И не просите меня защищать какие-либо дизайнерские решения. Я просто пытаюсь помочь решить проблему.)


Вот список того, что было предложено:

Ответ 2

Просто 8-битная чистка, по большей части. Тем не менее, вам нужно знать, что любой символ, отличный от ASCII, разбивается на несколько байтов, поэтому вы должны учитывать это, если текст или текст усечения для отображения.

UTF-8 имеет то преимущество, что вы всегда можете указать, где вы находитесь в многобайтовом символе: если бит 7 установлен, а бит 6 reset (байт равен 0x80-0xBF), это конечный байт, а если биты 7 и 6 устанавливаются, а 5 - reset (0xC0-0xDF), это старший байт с одним конечным байтом; если 7, 6 и 5 установлены, а 4 - reset (0xE0-0xEF), это старший байт с двумя байтами и т.д. Количество последовательных битов, установленных на самом значимом бите, - это общее количество байтов, составляющих символ. То есть:

110x xxxx = двухбайтовый символ
1110 xxxx = трехбайтовый символ
1111 0xxx = четырехбайтовый символ
и т.д.

Исландский алфавит содержится в ISO 8859-1 и, следовательно, Windows-1252. Если это приложение в консольном режиме, имейте в виду, что консоль использует кодовые страницы IBM, поэтому (в зависимости от локали системы) она может отображаться в 437, 850 или 861. У Windows нет встроенной поддержки отображения для UTF-8; вы должны преобразовать в UTF-16 и использовать Unicode API.

Вызов SetConsoleCP и SetConsoleOutputCP, определяющий кодовую страницу 1252, поможет с вашей проблемой, если это приложение в консольном режиме. К сожалению, выбранный шрифт консоли должен быть шрифтом, который поддерживает кодовую страницу, и я не вижу способа установить шрифт. Стандартные растровые шрифты поддерживают только стандартную кодовую страницу OEM по умолчанию.

Ответ 3

Помните, что полный юникод не соответствует 16-битным символам; поэтому либо используйте 32-битные символы, либо кодирование с переменной шириной (наиболее популярным является UTF-8).

Ответ 4

UTF-8 был разработан точно с учетом ваших проблем. Одна вещь, о которой я буду заботиться, это то, что ASCII - это действительно 7-битная кодировка, поэтому, если какая-либо часть вашей инфраструктуры использует 8-й бит для других целей, это может быть сложно.

Ответ 5

Возможно, вы захотите проверить icu. Они могут иметь доступные функции, которые облегчат работу с строками UTF-8.

Ответ 6

Исландский использует ISO Latin 1, поэтому должно быть достаточно восьми бит. Нам нужно больше деталей, чтобы выяснить, что происходит.

Ответ 7

Исландский, как французский, немецкий и большинство других языков Западной Европы, может поддерживаться с использованием 8-битного набора символов (CP1252 для Windows, ISO 8859-1, ака Latin1 on * x). Это был стандартный подход, прежде чем Unicode был изобретен, и по-прежнему довольно распространен. Как вы говорите, у вас есть ограничение, что вы не можете переписать приложение для использования wchar, и вам не нужно.

Не удивляйтесь, что UTF-8 вызывает проблемы; UTF-8 кодирует символы, отличные от ASCII (например, акцентированные латинские буквы, шип, eth и т.д.), Как ДВА БЫТЬ каждый.

Единственный общий совет, который можно дать, довольно прост (теоретически): (1) решить, какой набор символов вы собираетесь поддерживать (Unicode, Latin1, CP1252,...) в вашей системе (2), если вам предоставляются данные, закодированные каким-либо другим способом (например, UTF-8), затем перекодируйте его на свой стандарт (например, CP1252) на системной границе (3), если вам нужно предоставить данные, закодированные каким-то другим способом,...

Ответ 8

Вы можете использовать широкие символы (wchar_t вместо char и std:: wstring вместо std::string). Это автоматически не устраняет 100% ваших проблем, но является хорошим первым шагом.

Также используйте строковые функции, поддерживающие Unicode (см. документацию). Если что-то манипулирует широкими символами или строкой, обычно известно, что они широкие.