Как вы пишете код, который является безопасным для UTF-8? - PullRequest
10 голосов
/ 25 сентября 2008

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

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

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

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

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


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

Ответы [ 8 ]

10 голосов
/ 25 сентября 2008

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

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

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

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

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

3 голосов
/ 25 сентября 2008

Это похоже на исчерпывающее краткое руководство:
http://www.cl.cam.ac.uk/~mgk25/unicode.html

1 голос
/ 25 сентября 2008

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

1 голос
/ 25 сентября 2008

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

1 голос
/ 25 сентября 2008

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

0 голосов
/ 29 июня 2009

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

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

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

0 голосов
/ 25 сентября 2008

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

0 голосов
/ 25 сентября 2008

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

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

...