Информационное сообщение на русском языке, изначально записанное в 8-битном коде Windows, было

Обновлено: 02.07.2024

В этой главе объясняется, как выбрать набор символов. Он включает следующие темы:

Кодировка набора символов

Когда компьютерные системы обрабатывают символы, они используют числовые коды вместо графического представления символа. Например, когда в базе данных хранится буква A, на самом деле в ней хранится числовой код, интерпретируемый программным обеспечением как буква. Эти числовые коды особенно важны в глобальной среде из-за потенциальной необходимости преобразования данных между различными наборами символов.

Этот раздел включает следующие темы:

Что такое кодированный набор символов?

При создании базы данных вы указываете набор закодированных символов. Выбор набора символов определяет, какие языки могут быть представлены в базе данных. Это также влияет на:

Как вы создаете схему базы данных

Как вы разрабатываете приложения, обрабатывающие символьные данные

Как база данных работает с операционной системой

Для хранения данных символов требуется место для хранения

Группа символов (например, буквы алфавита, иероглифы, символы, знаки препинания и управляющие символы) может быть закодирована как набор символов. Закодированный набор символов назначает уникальные числовые коды каждому символу в репертуаре символов. Числовые коды называются кодовыми точками или закодированными значениями. В Табл. 2-1 показаны примеры символов, которым присвоено шестнадцатеричное кодовое значение в наборе символов ASCII.

Таблица 2-1 Символы, закодированные в наборе символов ASCII

Компьютерная индустрия использует множество кодированных наборов символов. Наборы символов различаются следующим образом:

Количество доступных символов

Доступные персонажи (репертуар персонажей)

Письма, используемые для письма, и языки, которые они представляют

Кодовые значения, присвоенные каждому символу

Схема кодирования, используемая для представления символа

Oracle поддерживает большинство национальных, международных и специфичных для поставщиков стандартов кодирования наборов символов.

"Наборы символов" для полного списка наборов символов, поддерживаемых Oracle

Какие символы закодированы?

Символы, закодированные в наборе символов, зависят от представленных систем письма. Система письма может использоваться для представления языка или группы языков. Системы письма можно разделить на две категории:

Этот раздел также включает следующие темы:

Системы фонетического письма

Системы фонетического письма состоят из символов, обозначающих различные звуки, связанные с языком. Греческий, латинский, кириллица и деванагари — все это примеры фонетических систем письма, основанных на алфавитах. Обратите внимание, что алфавиты могут представлять более одного языка. Например, латинский алфавит может представлять многие западноевропейские языки, такие как французский, немецкий и английский.

Символы, связанные с фонетической системой письма, обычно могут быть закодированы одним байтом, поскольку репертуар символов обычно меньше 256 символов.

Идеографические системы письма

Системы идеографического письма состоят из идеограмм или пиктограмм, которые представляют значение слова, а не звуки языка. Китайский и японский языки являются примерами систем идеографического письма, основанных на десятках тысяч идеограмм. Языки, использующие идеографические системы письма, также могут использовать слоговое письмо. Слоговые слова обеспечивают механизм для передачи дополнительной фонетической информации. Например, в японском есть два слоговых письма: хирагана, обычно используемая для грамматических элементов, и катакана, обычно используемая для иностранных и звукоподражательных слов.

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

Пунктуация, управляющие знаки, цифры и символы

Помимо кодирования алфавита языка необходимо кодировать и другие специальные символы:

Знаки препинания, такие как запятые, точки и апострофы

Специальные символы, такие как символы валюты и математические операторы

Управляющие символы, такие как возврат каретки и табуляция

Направление написания

Большинство западных языков пишут слева направо сверху вниз страницы. На восточноазиатских языках обычно пишут сверху вниз справа налево на странице, хотя для технических книг, переведенных с западных языков, часто делаются исключения. На арабском и иврите пишут справа налево сверху вниз.

Цифры в обратном направлении на арабском языке и иврите. Хотя текст пишется справа налево, числа в предложении пишутся слева направо. Например, «Я написал 32 книги» будет записано как «skoob 32 etorw I». Независимо от направления записи Oracle хранит данные в логическом порядке.Логический порядок означает порядок, в котором кто-то печатает язык, а не то, как он выглядит на экране.

Направление письма не влияет на кодировку символа.

Какие символы поддерживает набор символов?

Разные наборы символов поддерживают разные репертуары символов. Поскольку наборы символов обычно основаны на определенном сценарии письма, они могут поддерживать более одного языка. Когда наборы символов были впервые разработаны, у них был ограниченный набор символов. Даже сейчас могут быть проблемы с использованием определенных персонажей на разных платформах. Следующие символы CHAR и VARCHAR представлены во всех наборах символов базы данных Oracle и могут переноситься на любую платформу:

Прописные и строчные буквы английского алфавита от A до Z и от a до z

Арабские цифры от 0 до 9

Следующие управляющие символы: пробел, горизонтальная табуляция, вертикальная табуляция, перевод страницы

Если вы используете символы вне этого набора, позаботьтесь о том, чтобы ваши данные поддерживались в выбранном вами наборе символов базы данных.

Правильная установка параметра NLS_LANG необходима для правильного преобразования данных. Набор символов, заданный параметром NLS_LANG, должен отражать настройку операционной системы клиента. Правильная установка NLS_LANG обеспечивает правильное преобразование из кодировки символов клиентской операционной системы в набор символов базы данных. Если эти настройки совпадают, Oracle предполагает, что отправляемые или получаемые данные закодированы в том же наборе символов, что и набор символов базы данных, поэтому проверка или преобразование набора символов могут не выполняться. Это может привести к повреждению данных, если потребуется преобразование.

Во время преобразования из одного набора символов в другой Oracle ожидает, что данные на стороне клиента будут закодированы в наборе символов, заданном параметром NLS_LANG. Если вы поместите в строку другие значения (например, с помощью функций CHR или CONVERT SQL), то значения могут быть повреждены при отправке в базу данных, поскольку они не преобразованы должным образом. Если вы правильно сконфигурировали среду и если набор символов базы данных поддерживает весь репертуар символьных данных, которые могут быть введены в базу данных, вам не нужно изменять текущий набор символов базы данных. Однако, если ваше предприятие становится более глобальным и вам необходимо поддерживать дополнительные символы или новые языки, вам может потребоваться выбрать набор символов с более широким репертуаром символов. Корпорация Oracle рекомендует в таких случаях использовать базы данных и типы данных Unicode.

Справочник Oracle Database SQL для получения дополнительной информации о функциях CHR и CONVERT SQL

Кодировка ASCII

Таблица 2-2 показывает, как кодируется символ ASCII. Заголовки строк и столбцов обозначают шестнадцатеричные цифры. Чтобы найти закодированное значение символа, прочитайте номер столбца, за которым следует номер строки. Например, кодовое значение символа A равно 0x41.

Некоторая информация относится к предварительной версии продукта, которая может быть существенно изменена до ее выпуска. Microsoft не дает никаких явных или подразумеваемых гарантий в отношении представленной здесь информации.

Представляет кодировку символов.

Примеры

В следующем примере строка преобразуется из одной кодировки в другую.

Примечания

Обратите внимание, что кодирование предназначено для работы с символами Юникода, а не с произвольными двоичными данными, такими как массивы байтов. Если вам нужно кодировать произвольные двоичные данные в текст, вам следует использовать такой протокол, как uuencode, который реализуется с помощью таких методов, как Convert.ToBase64CharArray.

ASCIIEncoding кодирует символы Unicode как отдельные 7-битные символы ASCII. Эта кодировка поддерживает только значения символов между U+0000 и U+007F. Кодовая страница 20127. Также доступна через свойство ASCII.

UTF7Encoding кодирует символы Unicode с использованием кодировки UTF-7. Эта кодировка поддерживает все значения символов Unicode. Кодовая страница 65000. Также доступна через свойство UTF7.

UTF8Encoding кодирует символы Unicode с использованием кодировки UTF-8. Эта кодировка поддерживает все значения символов Unicode. Кодовая страница 65001. Также доступна через свойство UTF8.

UnicodeEncoding кодирует символы Unicode с использованием кодировки UTF-16. Поддерживаются как прямой, так и прямой порядок следования байтов. Также доступно через свойство Unicode и свойство BigEndianUnicode.

UTF32Encoding кодирует символы Unicode с использованием кодировки UTF-32. Поддерживаются как прямой (кодовая страница 12000), так и прямой порядок следования байтов (кодовая страница 12001). Также доступно через свойство UTF32.

Класс Encoding в первую очередь предназначен для преобразования между различными кодировками и Unicode. Часто один из производных классов Unicode является правильным выбором для вашего приложения.

Используйте метод GetEncoding, чтобы получить другие кодировки, и вызовите метод GetEncodings, чтобы получить список всех кодировок.

Список кодировок

Кодовые страницы, свойство EncodingInfo.Name которых соответствует международному стандарту, не обязательно полностью соответствуют этому стандарту.

В следующем примере вызываются методы GetEncoding(Int32) и GetEncoding(String) для получения кодировки греческой (Windows) кодовой страницы. Он сравнивает объекты Encoding, возвращенные вызовами метода, чтобы показать, что они равны, а затем отображает кодовую точку Unicode и соответствующее значение кодовой страницы для каждого символа греческого алфавита.

Если данные для преобразования доступны только в последовательных блоках (например, данные, считанные из потока) или если объем данных настолько велик, что его необходимо разделить на более мелкие блоки, следует использовать декодер или Кодировщик, предоставляемый методом GetDecoder или методом GetEncoder, соответственно, производного класса.

Кодировщики UTF-16 и UTF-32 могут использовать порядок байтов с прямым порядком байтов (сначала старший значащий байт) или с прямым порядком байтов (сначала младший значащий байт). Например, латинская заглавная буква A (U+0041) сериализуется следующим образом (в шестнадцатеричном формате):

Прямой порядок байтов UTF-16: 00 41

Прямой порядок байтов UTF-16: 41 00

Прямой порядок байтов UTF-32: 00 00 00 41

Прямой порядок байтов UTF-32: 41 00 00 00

Как правило, более эффективно хранить символы Юникода, используя собственный порядок байтов. Например, порядок байтов с прямым порядком байтов лучше использовать на платформах с прямым порядком байтов, таких как компьютеры Intel.

Метод GetPreamble извлекает массив байтов, включающий метку порядка байтов (BOM). Если этот массив байтов предшествует закодированному потоку, он помогает декодеру идентифицировать используемый формат кодирования.

Дополнительную информацию о порядке байтов и знаке порядка байтов см. в разделе Стандарт Unicode на главной странице Unicode.

Обратите внимание, что классы кодирования допускают ошибки:

Тихо изменить на "?" персонаж.

Используйте наиболее подходящий символ.

Изменение поведения в зависимости от приложения с помощью классов EncoderFallback и DecoderFallback с символом замены Unicode U+FFFD.

Вы должны создать исключение при любой ошибке потока данных. Приложение либо использует флаг «throwonerror», когда это применимо, либо использует классы EncoderExceptionFallback и DecoderExceptionFallback. Резервный вариант наилучшего вписывания часто не рекомендуется, поскольку он может привести к потере данных или путанице и выполняется медленнее, чем простая замена символов. Для кодировок ANSI наилучшим поведением является поведение по умолчанию.

Конструкторы

Инициализирует новый экземпляр класса Encoding.

Инициализирует новый экземпляр класса Encoding, соответствующий указанной кодовой странице.

Инициализирует новый экземпляр класса Encoding, соответствующий указанной кодовой странице, с указанными резервными стратегиями кодировщика и декодера.

Свойства

Получает кодировку для набора символов ASCII (7-бит).

Получает кодировку для формата UTF-16, в котором используется обратный порядок байтов.

При переопределении в производном классе получает имя для текущей кодировки, которое можно использовать с тегами тела почтового агента.

При переопределении в производном классе получает идентификатор кодовой страницы текущей кодировки.

Получает или задает объект DecoderFallback для текущего объекта Encoding.

Получает или задает объект EncoderFallback для текущего объекта Encoding.

При переопределении в производном классе получает удобочитаемое описание текущей кодировки.

При переопределении в производном классе получает имя для текущей кодировки, которое можно использовать с тегами заголовков почтового агента.

При переопределении в производном классе получает значение, указывающее, может ли текущая кодировка использоваться клиентами браузера для отображения контента.

При переопределении в производном классе получает значение, указывающее, может ли текущая кодировка использоваться клиентами браузера для сохранения содержимого.

При переопределении в производном классе получает значение, указывающее, может ли текущая кодировка использоваться почтовыми и новостными клиентами для отображения контента.

При переопределении в производном классе получает значение, указывающее, может ли текущая кодировка использоваться почтовыми и новостными клиентами для сохранения контента.

При переопределении в производном классе получает значение, указывающее, доступна ли текущая кодировка только для чтения.

При переопределении в производном классе получает значение, указывающее, использует ли текущая кодировка однобайтовые кодовые точки.

Получает кодировку для набора символов Latin1 (ISO-8859-1).

При переопределении в производном классе возвращает диапазон, содержащий последовательность байтов, указывающую используемую кодировку.

Получает кодировку для формата UTF-16 с прямым порядком байтов.

Получает кодировку для формата UTF-32 с прямым порядком байтов.

Получает кодировку для формата UTF-7.

Получает кодировку для формата UTF-8.

При переопределении в производном классе получает имя, зарегистрированное в Администрации адресного пространства Интернета (IANA) для текущей кодировки.

При переопределении в производном классе получает кодовую страницу операционной системы Windows, наиболее точно соответствующую текущей кодировке.

Методы

При переопределении в производном классе создает поверхностную копию текущего объекта Encoding.

Преобразует весь массив байтов из одной кодировки в другую.

Преобразует диапазон байтов в массиве байтов из одной кодировки в другую.

Создает поток, который служит для перекодирования данных между внутренним кодированием и внешним кодированием, аналогично Convert(Encoding, Encoding, Byte[]).

Определяет, равен ли указанный объект текущему экземпляру.

При переопределении в производном классе вычисляет количество байтов, полученных при кодировании набора символов, начиная с указанного указателя на символ.

При переопределении в производном классе вычисляет количество байтов, полученных при кодировании всех символов в указанном массиве символов.

При переопределении в производном классе вычисляет количество байтов, полученных при кодировании набора символов из указанного массива символов.

При переопределении в производном классе вычисляет количество байтов, полученных при кодировании символов в указанном диапазоне символов.

При переопределении в производном классе вычисляет количество байтов, полученных при кодировании символов в указанной строке.

При переопределении в производном классе вычисляет количество байтов, полученных при кодировании набора символов из указанной строки.

При переопределении в производном классе кодирует набор символов, начиная с указанного указателя символа, в последовательность байтов, которые сохраняются, начиная с указанного указателя байта.

При переопределении в производном классе кодирует все символы указанного массива символов в последовательность байтов.

При переопределении в производном классе кодирует набор символов из указанного массива символов в последовательность байтов.

При переопределении в производном классе кодирует набор символов из указанного массива символов в указанный массив байтов.

При переопределении в производном классе кодирует в диапазон байтов набор символов из указанного диапазона, доступного только для чтения.

При переопределении в производном классе кодирует все символы указанной строки в последовательность байтов.

При переопределении в производном классе кодирует в массив байтов количество символов, указанное в параметре count в указанной строке, начиная с указанного индекса .

При переопределении в производном классе кодирует набор символов из указанной строки в указанный массив байтов.

При переопределении в производном классе вычисляет количество символов, полученных при декодировании последовательности байтов, начиная с указанного указателя байта.

При переопределении в производном классе вычисляет количество символов, полученных путем декодирования всех байтов в указанном массиве байтов.

При переопределении в производном классе вычисляет количество символов, полученных путем декодирования последовательности байтов из указанного массива байтов.

При переопределении в производном классе вычисляет количество символов, полученных путем декодирования предоставленного диапазона байтов, доступного только для чтения.

При переопределении в производном классе декодирует последовательность байтов, начиная с указанного указателя байта, в набор символов, которые сохраняются, начиная с указанного указателя символа.

При переопределении в производном классе декодирует все байты в указанном массиве байтов в набор символов.

При переопределении в производном классе декодирует последовательность байтов из указанного массива байтов в набор символов.

При переопределении в производном классе декодирует последовательность байтов из указанного массива байтов в указанный массив символов.

При переопределении в производном классе декодирует все байты в указанном диапазоне байтов только для чтения в диапазон символов.

При переопределении в производном классе получает декодер, преобразующий закодированную последовательность байтов в последовательность символов.

При переопределении в производном классе получает кодировщик, преобразующий последовательность символов Unicode в закодированную последовательность байтов.

Возвращает кодировку, связанную с указанным идентификатором кодовой страницы.

Возвращает кодировку, связанную с указанным идентификатором кодовой страницы. Параметры определяют обработчик ошибок для символов, которые невозможно закодировать, и последовательностей байтов, которые невозможно декодировать.

Возвращает кодировку, связанную с указанным именем кодовой страницы.

Возвращает кодировку, связанную с указанным именем кодовой страницы. Параметры определяют обработчик ошибок для символов, которые невозможно закодировать, и последовательностей байтов, которые невозможно декодировать.

Возвращает массив, содержащий все кодировки.

Возвращает хэш-код для текущего экземпляра.

При переопределении в производном классе вычисляет максимальное количество байтов, полученных при кодировании указанного количества символов.

При переопределении в производном классе вычисляет максимальное количество символов, полученных при декодировании указанного количества байтов.

При переопределении в производном классе возвращает последовательность байтов, указывающую используемую кодировку.

При переопределении в производном классе декодирует указанное количество байтов, начиная с указанного адреса, в строку.

При переопределении в производном классе декодирует все байты в указанном массиве байтов в строку.

При переопределении в производном классе декодирует последовательность байтов из указанного массива байтов в строку.

При переопределении в производном классе декодирует все байты в указанном диапазоне байтов в строку.

Получает тип текущего экземпляра.

Получает значение, указывающее, всегда ли нормализуется текущая кодировка с использованием формы нормализации по умолчанию.

При переопределении в производном классе получает значение, указывающее, всегда ли нормализуется текущая кодировка с использованием указанной формы нормализации.

Создает поверхностную копию текущего объекта.

Регистрирует поставщика кодирования.

Возвращает строку, представляющую текущий объект.

Методы расширения

Кодирует указанную последовательность ReadOnlySequence в массив байтов, используя указанную кодировку.

Декодирует указанную ReadOnlySequence в байты, используя указанную кодировку, и записывает результат в модуль записи.

Кодирует указанный ReadOnlySequence в byte s с использованием указанного Encoding и выводит результат в bytes .

Кодирует указанный ReadOnlySpan в байты, используя указанную кодировку, и записывает результат в модуль записи.

Декодирует указанную ReadOnlySequence в char с использованием указанной кодировки и записывает результат в записывающее устройство.

Декодирует указанный ReadOnlySequence в char с использованием указанного Encoding и выводит результат в chars .

Декодирует указанный ReadOnlySpan в char с использованием указанной кодировки и записывает результат в модуль записи.

Декодирует указанную ReadOnlySequence в строку, используя указанную кодировку.

Кодировщики и декодеры

Кодирование и декодирование также могут включать проверку. Например, класс UnicodeEncoding проверяет все экземпляры char в суррогатном диапазоне, чтобы убедиться, что они находятся в допустимых суррогатных парах. Стратегия отката определяет, как кодировщик обрабатывает недопустимые символы или как декодер обрабатывает недопустимые байты.

Вызвать конструктор класса кодировки. Таким образом могут создаваться объекты для кодировок ASCII, UTF-7, UTF-8, UTF-16 и UTF-32. По умолчанию каждый объект использует запасной вариант замены для обработки строк, которые он не может закодировать, и байтов, которые он не может декодировать, но вы можете указать, что вместо этого должно создаваться исключение. Дополнительные сведения см. в разделах Резервный вариант замены и Резервный вариант исключения.

Вызовите конструктор Encoding(Int32) и передайте ему целое число, представляющее кодировку. Стандартные объекты кодирования используют замещающий резервный вариант, а объекты кодирования кодовой страницы и двухбайтового набора символов (DBCS) используют наиболее подходящий резервный вариант для обработки строк, которые они не могут кодировать, и байтов, которые они не могут декодировать. Дополнительную информацию см. в разделе Наилучшее резервное копирование.

Эти кодировки позволяют работать с символами Unicode, а также с кодировками, которые чаще всего используются в устаревших приложениях. Кроме того, вы можете создать собственную кодировку, определив класс, производный от Encoding, и переопределив его члены.

Выбор класса кодирования

Если вы планируете использовать кодировку ASCII (ASCIIEncoding), вместо этого выберите UTF8Encoding. Эти две кодировки идентичны для набора символов ASCII, но UTF8Encoding имеет следующие преимущества:

Он может представлять каждый символ Юникода, тогда как ASCIIEncoding поддерживает только значения символов Юникода между U+0000 и U+007F.

Он обеспечивает обнаружение ошибок и повышает безопасность.

Он был настроен так, чтобы быть максимально быстрым и должен быть быстрее, чем любая другая кодировка. Даже для содержимого, полностью состоящего из ASCII, операции, выполняемые с кодировкой UTF8Encoding, выполняются быстрее, чем операции, выполняемые с кодировкой ASCIIEncoding.

Вы должны рассмотреть возможность использования ASCIIEncoding только для устаревших приложений. Однако даже для устаревших приложений UTF8Encoding может быть лучшим выбором по следующим причинам (при настройках по умолчанию):

Если в вашем приложении есть контент, который не является строго ASCII и кодируется с помощью ASCIIEncoding, каждый символ, отличный от ASCII, кодируется как вопросительный знак (?). Если приложение затем декодирует эти данные, информация будет потеряна.

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

Использование объекта кодирования

Кодер преобразует строку символов (чаще всего символов Unicode) в ее числовой (байтовый) эквивалент. Например, вы можете использовать кодировщик ASCII для преобразования символов Unicode в ASCII, чтобы их можно было отобразить на консоли. Чтобы выполнить преобразование, вы вызываете метод Encoding.GetBytes. Если вы хотите определить, сколько байтов необходимо для хранения закодированных символов перед выполнением кодирования, вы можете вызвать метод GetByteCount.

В следующем примере используется однобайтовый массив для кодирования строк в двух отдельных операциях. Он поддерживает индекс, указывающий начальную позицию в массиве байтов для следующего набора байтов в кодировке ASCII. Он вызывает метод ASCIIEncoding.GetByteCount(String), чтобы убедиться, что массив байтов достаточно велик для размещения закодированной строки. Затем он вызывает метод ASCIIEncoding.GetBytes(String, Int32, Int32, Byte[], Int32) для кодирования символов в строке.

Декодер преобразует массив байтов, отражающий конкретную кодировку символов, в набор символов либо в массиве символов, либо в строке. Чтобы декодировать массив байтов в массив символов, вы вызываете метод Encoding.GetChars. Чтобы декодировать массив байтов в строку, вы вызываете метод GetString. Если вы хотите определить, сколько символов необходимо для хранения декодированных байтов перед выполнением декодирования, вы можете вызвать метод GetCharCount.

В следующем примере три строки кодируются, а затем декодируются в один массив символов. Он поддерживает индекс, указывающий начальную позицию в массиве символов для следующего набора декодированных символов. Он вызывает метод GetCharCount, чтобы убедиться, что массив символов достаточно велик для размещения всех декодированных символов. Затем он вызывает метод ASCIIEncoding.GetChars(Byte[], Int32, Int32, Char[], Int32) для декодирования массива байтов.

Методы кодирования и декодирования класса, производного от Encoding, предназначены для работы с полным набором данных; то есть все данные, которые должны быть закодированы или декодированы, предоставляются в одном вызове метода. Однако в некоторых случаях данные доступны в потоке, а данные, подлежащие кодированию или декодированию, могут быть доступны только из отдельных операций чтения. Это требует, чтобы операция кодирования или декодирования запоминала любое сохраненное состояние из предыдущего вызова. Методы классов, производных от Encoder и Decoder, могут обрабатывать операции кодирования и декодирования, охватывающие несколько вызовов методов.

Объект Encoder для конкретной кодировки доступен из свойства Encoding.GetEncoder этой кодировки. Объект Decoder для конкретной кодировки доступен из свойства Encoding.GetDecoder этой кодировки. Обратите внимание, что для операций декодирования классы, производные от Decoder, включают метод Decoder.GetChars, но не имеют метода, соответствующего Encoding.GetString.

В следующем примере показана разница между использованием методов Encoding.GetString и Decoder.GetChars для декодирования массива байтов Unicode. В примере строка, содержащая некоторые символы Юникода, кодируется в файл, а затем используются два метода декодирования для их декодирования по десять байтов за раз. Поскольку суррогатная пара находится в десятом и одиннадцатом байтах, она декодируется в отдельных вызовах метода. Как видно из выходных данных, метод Encoding.GetString не может правильно декодировать байты и вместо этого заменяет их на U+FFFD (REPLACEMENT CHARACTER). С другой стороны, метод Decoder.GetChars может успешно декодировать массив байтов, чтобы получить исходную строку.

Выбор запасной стратегии

Когда метод пытается закодировать или декодировать символ, но сопоставление не существует, он должен реализовать резервную стратегию, которая определяет, как следует обрабатывать неудачное сопоставление. Существует три типа резервных стратегий:

Наиболее распространенные проблемы в операциях кодирования возникают, когда символ Unicode не может быть сопоставлен с определенной кодировкой кодовой страницы. Наиболее распространенные проблемы в операциях декодирования возникают, когда недопустимые последовательности байтов не могут быть преобразованы в допустимые символы Unicode. По этим причинам вы должны знать, какую резервную стратегию использует конкретный объект кодирования. По возможности следует указать резервную стратегию, используемую объектом кодирования, при создании экземпляра объекта.

Оптимальный резерв

Если символ не имеет точного соответствия в целевой кодировке, кодировщик может попытаться сопоставить его с похожим символом. (Резервный вариант наилучшего соответствия в основном связан с кодировкой, а не с декодированием. Существует очень мало кодовых страниц, содержащих символы, которые не могут быть успешно сопоставлены с Unicode.) Наилучший резервный вариант используется по умолчанию для кодовых страниц и кодировок двухбайтовых наборов символов, извлекаемых с помощью перегрузок Encoding.GetEncoding(Int32) и Encoding.GetEncoding(String).

Оптимальные стратегии различаются для разных кодовых страниц. Например, для некоторых кодовых страниц латинские символы полной ширины сопоставляются с более распространенными латинскими символами половинной ширины. Для других кодовых страниц это сопоставление не выполняется. Даже при агрессивной стратегии наилучшего соответствия невозможно вообразить соответствие некоторых символов в некоторых кодировках. Например, китайский иероглиф не имеет разумного сопоставления с кодовой страницей 1252. В этом случае используется строка замены. По умолчанию эта строка представляет собой один ВОПРОСИТЕЛЬНЫЙ ЗНАК (U+003F).

Оптимальные стратегии подробно не задокументированы. Однако несколько кодовых страниц задокументированы на веб-сайте Консорциума Unicode. Просмотрите файл readme.txt в этой папке, чтобы узнать, как интерпретировать файлы сопоставления.

В следующем примере используется кодовая страница 1252 (кодовая страница Windows для западноевропейских языков), чтобы проиллюстрировать наиболее подходящее сопоставление и его недостатки. Метод Encoding.GetEncoding(Int32) используется для извлечения объекта кодировки для кодовой страницы 1252. По умолчанию он использует наиболее подходящее сопоставление для символов Unicode, которые он не поддерживает. В примере создается строка, содержащая три не-ASCII-символа — ЗАГЛАВНАЯ ЛАТИНСКАЯ БУКВА S (U+24C8), ВЕРХНЯЯ ПЯТЬ (U+2075) и БЕСКОНЕЧНОСТЬ (U+221E), разделенные пробелами. Как видно из выходных данных примера, при кодировании строки три исходных не пробельных символа заменяются ЗНАКОМ ВОПРОСА (U+003F), ПЯТОЙ ЦИФРОЙ (U+0035) и ЦИФРОЙ ВОСЕМЬ (U+0038). ЦИФРА ВОСЕМЬ – особенно плохая замена неподдерживаемому символу БЕСКОНЕЧНОСТЬ, а ЗНАК ВОПРОСА означает, что для исходного символа не было возможности сопоставления.

Наилучшее сопоставление — это поведение по умолчанию для объекта Encoding, который кодирует данные Unicode в данные кодовой страницы, и существуют устаревшие приложения, которые полагаются на это поведение. Однако большинству новых приложений следует избегать оптимального поведения из соображений безопасности. Например, приложения не должны помещать доменное имя в наиболее подходящую кодировку.

Вы также можете реализовать собственное резервное сопоставление для кодировки. Дополнительные сведения см. в разделе «Реализация пользовательской резервной стратегии».

Если по умолчанию для объекта кодирования используется наиболее подходящий резервный вариант, вы можете выбрать другую резервную стратегию при извлечении объекта Encoding, вызвав метод Encoding.GetEncoding(Int32, EncoderFallback, DecoderFallback) или Encoding.GetEncoding(String, EncoderFallback, DecoderFallback) перегружен. В следующем разделе приведен пример, в котором каждый символ, который не может быть сопоставлен с кодовой страницей 1252, заменяется звездочкой (*).

Запасной вариант

Если символ не имеет точного соответствия в целевой схеме, но нет подходящего символа, с которым его можно сопоставить, приложение может указать замещающий символ или строку. Это поведение по умолчанию для декодера Unicode, который заменяет любую двухбайтовую последовательность, которую он не может декодировать, на REPLACEMENT_CHARACTER (U+FFFD). Это также поведение по умолчанию класса ASCIIEncoding, который заменяет каждый символ, который не может быть закодирован или декодирован, знаком вопроса. В следующем примере показана замена символов в строке Unicode из предыдущего примера. Как видно из выходных данных, каждый символ, который не может быть декодирован в байтовое значение ASCII, заменяется на 0x3F, который является кодом ASCII для вопросительного знака.

Вы также можете реализовать замещающий класс для кодировки. Дополнительные сведения см. в разделе «Реализация пользовательской резервной стратегии».

В дополнение к ВОПРОСИТЕЛЬНОМУ ЗНАКУ (U+003F) в качестве замещающей строки обычно используется ЗАМЕНЯЮЩИЙ СИМВОЛ Юникода (U+FFFD), особенно при декодировании последовательностей байтов, которые невозможно успешно преобразовать в символы Юникода. Однако вы можете выбрать любую строку замены, и она может содержать несколько символов.

Резервное исключение

Вместо того, чтобы предоставлять наиболее подходящий запасной вариант или строку замены, кодировщик может генерировать исключение EncoderFallbackException, если он не может закодировать набор символов, а декодер может генерировать исключение DecoderFallbackException, если он не может декодировать массив байтов. Чтобы вызвать исключение в операциях кодирования и декодирования, вы предоставляете объект EncoderExceptionFallback и объект DecoderExceptionFallback соответственно методу Encoding.GetEncoding(String, EncoderFallback, DecoderFallback). В следующем примере показан резервный вариант исключения с помощью класса ASCIIEncoding.

Вы также можете реализовать собственный обработчик исключений для операции кодирования. Дополнительные сведения см. в разделе «Реализация пользовательской резервной стратегии».

Объекты EncoderFallbackException и DecoderFallbackException предоставляют следующую информацию об условии, вызвавшем исключение:

Объект DecoderFallbackException включает свойство BytesUnknown, которое возвращает массив байтов, которые невозможно декодировать. Свойство DecoderFallbackException.Index указывает начальную позицию неизвестных байтов.

Хотя объекты EncoderFallbackException и DecoderFallbackException предоставляют достаточную диагностическую информацию об исключении, они не предоставляют доступ к буферу кодирования или декодирования. Поэтому они не позволяют заменять или исправлять неверные данные в рамках метода кодирования или декодирования.

Реализация пользовательской резервной стратегии

Кроме того, вы можете реализовать индивидуальное решение, в котором используется наиболее подходящий резервный вариант, резервный вариант замены или резервный вариант исключения, выполнив следующие действия:

Наследуйте класс от EncoderFallback для операций кодирования и от класса DecoderFallback для операций декодирования.

Наследуйте класс от EncoderFallbackBuffer для операций кодирования и от класса DecoderFallbackBuffer для операций декодирования.

Для отката исключения, если предопределенные классы EncoderFallbackException и DecoderFallbackException не соответствуют вашим потребностям, создайте класс на основе объекта исключения, такого как Exception или ArgumentException.

Производный от EncoderFallback или DecoderFallback

Чтобы реализовать собственное резервное решение, необходимо создать класс, наследуемый от EncoderFallback для операций кодирования и от DecoderFallback для операций декодирования. Экземпляры этих классов передаются методу Encoding.GetEncoding(String, EncoderFallback, DecoderFallback) и служат посредником между классом кодирования и резервной реализацией.

При создании пользовательского резервного решения для кодировщика или декодера необходимо реализовать следующие элементы:

Свойство EncoderFallback.MaxCharCount или DecoderFallback.MaxCharCount, которое возвращает максимально возможное количество символов, которое может вернуть наиболее подходящий вариант, замена или резервный вариант исключения для замены одного символа. Для резервного варианта пользовательского исключения его значение равно нулю.

Метод EncoderFallback.CreateFallbackBuffer или DecoderFallback.CreateFallbackBuffer, который возвращает вашу пользовательскую реализацию EncoderFallbackBuffer или DecoderFallbackBuffer. Этот метод вызывается кодировщиком, когда он встречает первый символ, который не может успешно закодировать, или декодером, когда он встречает первый байт, который не может успешно декодировать.

Производный от EncoderFallbackBuffer или DecoderFallbackBuffer

Чтобы реализовать собственное резервное решение, необходимо также создать класс, наследуемый от EncoderFallbackBuffer для операций кодирования и от DecoderFallbackBuffer для операций декодирования. Экземпляры этих классов возвращаются методом CreateFallbackBuffer классов EncoderFallback и DecoderFallback. Метод EncoderFallback.CreateFallbackBuffer вызывается кодировщиком при обнаружении первого символа, который он не может закодировать, а метод DecoderFallback.CreateFallbackBuffer вызывается декодером при обнаружении одного или нескольких байтов, которые он не может декодировать. Классы EncoderFallbackBuffer и DecoderFallbackBuffer предоставляют резервную реализацию. Каждый экземпляр представляет собой буфер, содержащий резервные символы, которые заменят символ, который невозможно закодировать, или последовательность байтов, которую невозможно декодировать.

При создании пользовательского резервного решения для кодировщика или декодера необходимо реализовать следующие элементы:

Метод EncoderFallbackBuffer.Fallback или DecoderFallbackBuffer.Fallback. EncoderFallbackBuffer.Fallback вызывается кодировщиком для предоставления резервному буферу информации о символе, который он не может закодировать. Поскольку кодируемый символ может быть суррогатной парой, этот метод перегружен. Одной перегрузке передается кодируемый символ и его индекс в строке. Второй перегрузке передается старший и младший суррогат вместе с его индексом в строке. Метод DecoderFallbackBuffer.Fallback вызывается декодером для предоставления резервному буферу информации о байтах, которые он не может декодировать. Этому методу передается массив байтов, которые он не может декодировать, вместе с индексом первого байта. Резервный метод должен возвращать значение true, если резервный буфер может предоставить наиболее подходящий или замещающий символ или символы; в противном случае он должен вернуть false . Для отката исключения метод отката должен генерировать исключение.

Метод EncoderFallbackBuffer.GetNextChar или DecoderFallbackBuffer.GetNextChar, который многократно вызывается кодировщиком или декодером для получения следующего символа из резервного буфера. Когда все резервные символы будут возвращены, метод должен вернуть U+0000.

Свойство EncoderFallbackBuffer.Remaining или DecoderFallbackBuffer.Remaining, которое возвращает количество символов, оставшихся в резервном буфере.

EncoderFallbackBuffer.MovePrevious или DecoderFallbackBuffer.MovePrevious, который перемещает текущую позицию в резервном буфере на предыдущий символ.

Метод EncoderFallbackBuffer.Reset или DecoderFallbackBuffer.Reset, который повторно инициализирует резервный буфер.

Если резервная реализация является наиболее подходящей или заменяющей резервной версией, классы, производные от EncoderFallbackBuffer и DecoderFallbackBuffer, также поддерживают два закрытых поля экземпляра: точное количество символов в буфере; и индекс следующего возвращаемого символа в буфере.

Пример резервного кодировщика

В более раннем примере использовалась резервная замена для замены символов Unicode, не соответствующих символам ASCII, на звездочку (*). В следующем примере вместо этого используется пользовательская наилучшая резервная реализация, обеспечивающая лучшее сопоставление символов, отличных от ASCII.

Следующий код определяет класс CustomMapperFallbackBuffer, производный от EncoderFallbackBuffer. Словарь, содержащий наиболее подходящие сопоставления и определенный в экземпляре CustomMapper, доступен из его конструктора класса. Его метод Fallback возвращает значение true, если какой-либо из символов Unicode, которые кодировщик ASCII не может закодировать, определен в словаре сопоставления; в противном случае возвращается false . Для каждого резервного варианта частная переменная count указывает количество символов, которые осталось вернуть, а частная индексная переменная указывает положение в строковом буфере charsToReturn следующего возвращаемого символа.

Сопоставляет строку символов со строкой UTF-16 (расширенные символы). Строка символов не обязательно относится к многобайтовому набору символов.

Внимание! Неправильное использование функции MultiByteToWideChar может поставить под угрозу безопасность вашего приложения. Вызов этой функции может легко привести к переполнению буфера, поскольку размер входного буфера, указанный параметром lpMultiByteStr, равен количеству байтов в строке, а размер выходного буфера, указанный параметром lpWideCharStr равно количеству символов. Чтобы избежать переполнения буфера, ваше приложение должно указать размер буфера, соответствующий типу данных, которые буфер получает. Дополнительные сведения см. в разделе Вопросы безопасности: международные функции.

Примечание. Кодовые страницы ANSI могут быть разными на разных компьютерах или могут быть изменены для одного компьютера, что приведет к повреждению данных. Для наиболее согласованных результатов приложения должны использовать Юникод, например UTF-8 или UTF-16, вместо определенной кодовой страницы, если устаревшие стандарты или форматы данных не запрещают использование Юникода. Если использование Unicode невозможно, приложения должны пометить поток данных соответствующим именем кодировки, если это разрешено протоколами. Файлы HTML и XML позволяют добавлять теги, а текстовые файлы — нет.

Синтаксис

Параметры

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

Примечание. Это значение может быть разным на разных компьютерах, даже в одной сети. Его можно изменить на том же компьютере, что приведет к необратимому повреждению сохраненных данных. Это значение предназначено только для временного использования, а для постоянного хранения следует использовать кодировку UTF-16 или UTF-8, если это возможно.

Примечание. Это значение может быть разным на разных компьютерах, даже в одной сети. Его можно изменить на том же компьютере, что приведет к необратимому повреждению сохраненных данных. Это значение предназначено только для временного использования, а для постоянного хранения следует использовать кодировку UTF-16 или UTF-8, если это возможно.

Примечание. Это значение в основном используется в устаревшем коде и обычно не требуется, поскольку современные компьютеры Macintosh используют Unicode для кодирования.

Примечание. Это значение может быть разным на разных компьютерах, даже в одной сети. Его можно изменить на том же компьютере, что приведет к необратимому повреждению сохраненных данных. Это значение предназначено только для временного использования, а для постоянного хранения следует использовать кодировку UTF-16 или UTF-8, если это возможно.

Примечание. Это значение может быть разным на разных компьютерах, даже в одной сети. Его можно изменить на том же компьютере, что приведет к необратимому повреждению сохраненных данных. Это значение предназначено только для временного использования, а для постоянного хранения следует использовать кодировку UTF-16 или UTF-8, если это возможно.

Флаги, указывающие на тип конверсии. Приложение может указать комбинацию следующих значений, при этом MB_PRECOMPOSED является значением по умолчанию. MB_PRECOMPOSED и MB_COMPOSITE являются взаимоисключающими. MB_USEGLYPHCHARS и MB_ERR_INVALID_CHARS можно установить независимо от состояния других флагов.

Начиная с Windows Vista, функция не отбрасывает недопустимые кодовые точки, если приложение не устанавливает этот флаг, а вместо этого заменяет недопустимые последовательности на U+FFFD (закодированные в соответствии с указанной кодовой страницей).

Windows 2000 с пакетом обновления 4 (SP4) и более поздние версии, Windows XP: если этот флаг не установлен, функция автоматически отбрасывает недопустимые кодовые точки. Вызов GetLastError возвращает ERROR_NO_UNICODE_TRANSLATION.

Для перечисленных ниже кодовых страниц параметру dwFlags должно быть присвоено значение 0. В противном случае функция завершается с ошибкой ERROR_INVALID_FLAGS.

  • 50220
  • 50221
  • 50222
  • 50225
  • 50227
  • 50229
  • 57002–57011
  • 65000 (UTF-7)
  • 42 (символ)

Примечание. Для UTF-8 или кодовой страницы 54936 (GB18030, начиная с Windows Vista) для параметра dwFlags должно быть установлено значение 0 или MB_ERR_INVALID_CHARS. В противном случае функция завершается с ошибкой ERROR_INVALID_FLAGS.

Указатель на строку символов для преобразования.

Размер в байтах строки, указанной параметром lpMultiByteStr. В качестве альтернативы этому параметру можно задать значение -1, если строка завершается нулем. Обратите внимание, что если cbMultiByte равно 0, функция завершается ошибкой.

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

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

[выходной, необязательный] lpWideCharStr

Указатель на буфер, который получает преобразованную строку.

Размер буфера в символах, указанный параметром lpWideCharStr. Если это значение равно 0, функция возвращает требуемый размер буфера в символах, включая любой завершающий нулевой символ, и не использует буфер lpWideCharStr.

Возвращаемое значение

В случае успеха возвращает количество символов, записанных в буфер, указанный параметром lpWideCharStr. Если функция завершается успешно и cchWideChar равно 0, возвращаемое значение является требуемым размером в символах для буфера, указанного lpWideCharStr. Также см. dwFlags для получения информации о том, как флаг MB_ERR_INVALID_CHARS влияет на возвращаемое значение при вводе недопустимых последовательностей.

Функция возвращает 0 в случае неудачи. Чтобы получить расширенную информацию об ошибке, приложение может вызвать функцию GetLastError, которая может вернуть один из следующих кодов ошибки:

  • ОШИБКА_INSUFFICIENT_BUFFER. Предоставленный размер буфера был недостаточно большим или для него было неправильно установлено значение NULL.
  • ОШИБКА_INVALID_FLAGS. Значения, предоставленные для флагов, недействительны.
  • ОШИБКА_INVALID_PARAMETER. Любое из значений параметра было недопустимым.
  • ОШИБКА_NO_UNICODE_TRANSLATION. В строке обнаружен недопустимый Unicode.

Примечания

Поведение этой функции по умолчанию заключается в преобразовании в предварительно составленную форму строки входных символов. Если предварительно составленная форма не существует, функция пытается преобразовать ее в составную форму.

Использование флага MB_PRECOMPOSED очень мало влияет на большинство кодовых страниц, поскольку большая часть входных данных уже составлена. Рассмотрите возможность вызова NormalizeString после преобразования с помощью MultiByteToWideChar. NormalizeString предоставляет более точные, стандартные и согласованные данные, а также может работать быстрее. Обратите внимание, что для перечисления NORM_FORM, передаваемого в NormalizeString, NormalizationC соответствует MB_PRECOMPOSED, а NormalizationD соответствует MB_COMPOSITE.

Как упоминалось в предупреждении выше, выходной буфер может быть легко переполнен, если эта функция не вызывается сначала с cchWideChar, установленным в 0, чтобы получить требуемый размер. Если используется флаг MB_COMPOSITE, вывод может состоять из трех или более символов для каждого входного символа.

Указатели lpMultiByteStr и lpWideCharStr не должны совпадать. Если они совпадают, функция завершается ошибкой, и GetLastError возвращает значение ERROR_INVALID_PARAMETER.

MultiByteToWideChar не завершает нулем выходную строку, если длина входной строки явно указана без завершающего нулевого символа. Чтобы завершать нулем выходную строку для этой функции, приложение должно передать -1 или явно подсчитать завершающий нулевой символ для входной строки.

Функция завершается ошибкой, если установлен параметр MB_ERR_INVALID_CHARS и в исходной строке встречается недопустимый символ. Недопустимым символом является один из следующих:

  • Символ, который не является символом по умолчанию в исходной строке, но преобразуется в символ по умолчанию, если не задан параметр MB_ERR_INVALID_CHARS
  • Для строк DBCS: символ, который имеет начальный байт, но не имеет допустимого завершающего байта.

Windows XP: чтобы предотвратить проблему безопасности некратчайших форм символов UTF-8, MultiByteToWideChar удаляет эти символы.

Читайте также: