Использование классов кодировки символов в .NET

Использование классов кодировки символов в .NET

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

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

.NET предоставляет классы кодировки для кодирования и декодирования текста с помощью различных систем кодирования. Например, класс UTF8Encoding описывает правила кодирования и декодирования UTF-8. Для экземпляров string .NET использует кодировку UTF-16 (представленную классом UnicodeEncoding). Кодировщики и декодеры доступны для других схем кодирования.

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

Классы кодировок .NET позволяют хранить и преобразовывать символьные данные. Их не следует использовать для хранения двоичных данных в строковом виде. В зависимости от используемой кодировки преобразование двоичных данных в строковый формат с использованием классов кодировок может привести к неожиданному результату и неточным или поврежденным данным. Для преобразования двоичных данных в строковый формат используйте метод Convert.ToBase64String .

Все классы кодировок в .NET наследуют от абстрактного класса System.Text.Encoding, который определяет общую для всех кодировок функциональность. Для доступа к отдельным объектам кодировок, реализованным в .NET, можно сделать следующее:

Используйте статические свойства класса Encoding, которые возвращают объекты, представляющие стандартные кодировки символов .NET (ASCII, UTF-7, UTF-8, UTF-16 и UTF-32). Например, свойство Encoding.Unicode возвращает объект UnicodeEncoding . Каждый объект использует резервную стратегию замены для обработки строк, которые он не может закодировать, и байтов, которые не может декодировать. Дополнительные сведения см. в разделе Replacement fallback.

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

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

Вызовите метод Encoding.GetEncoding, возвращающий любую стандартную кодировку, кодовую страницу или кодировку DBCS, доступную в .NET. Перегрузки позволяют задать резервный объект как для кодировщика, так и для декодера.

Информацию обо всех доступных в .NET кодировках можно получить, вызвав метод Encoding.GetEncodings. Платформа .NET поддерживает схемы кодировки символов, перечисленные в таблице ниже.

Класс кодировки Описание ASCII Кодирует ограниченный диапазон символов, используя семь младших битов байта. Так как эта кодировка поддерживает только значения символов от U+0000 до U+007F, то в большинстве случаев она не отвечает требованиям международных приложений. UTF-7 Представляет символы в виде последовательностей 7-разрядных символов ASCII. Символы Юникода, не относящиеся к ASCII, представляются в виде escape-последовательности символов ASCII. UTF-7 поддерживает протоколы, например электронной почты и группы новостей. Однако формат UTF-7 недостаточно безопасен и надежен. В некоторых случаях изменение одного бита может привести к существенному изменению интерпретации всей строки UTF-7. В других случаях для кодировки одного и того же текста могут использоваться разные строки UTF-7. В последовательностях, содержащих отличные от ASCII символы, формат UTF-7 требует больше места, чем UTF-8, а кодирование и декодирование выполняются медленнее. Поэтому по возможности лучше использовать UTF-8 вместо UTF-7. UTF-8 Представляет каждую кодовую точку Юникода в виде последовательности от одного до четырех байтов. UTF-8 поддерживает 8-разрядный размер данных и хорошо работает со многими операционными системами. Для диапазона символов ASCII кодировка UTF-8 идентична кодировке ASCII и предоставляет более широкий набор символов. Однако для китайской, японской и корейской письменности UTF-8 может потребовать три байта для каждого символа, что может привести к большему объему данных по сравнению с UTF-16. Иногда увеличение размера данных для китайской, японской и корейской письменности объясняется объемом данных ASCII, например тегами HTML. UTF-16 Представляет каждую кодовую точку Юникода в виде последовательности одного или двух 16-разрядных целых чисел. Наиболее распространенные символы Юникода требуют только одной кодовой точки UTF-16, хотя дополнительные символы Юникода (U+10000 и далее) требуют двух замещающих кодовых точек UTF-16. Поддерживаются оба порядка байтов: прямой и обратный. Кодировка UTF-16 используется средой CLR для представления значений Char и String , а операционной системой Windows — для представления значений WCHAR . UTF-32 Представляет каждую кодовую точку Юникода в виде 32-разрядного целого числа. Поддерживаются оба порядка байтов: прямой и обратный. Кодировка UTF-32 используется в случае, когда приложению требуется избежать поведения замещающей кодовой точки кодировки UTF-16 в операционных системах, в которых закодированное пространство имеет большое значение. Для кодирования отдельных отображаемых глифов может использоваться несколько символов UTF-32. Кодировка ANSI и ISO Предоставляет поддержку ряда кодовых страниц. В операционных системах Windows кодовые страницы используются для поддержки конкретного языка или группы языков. Таблицу кодовых страниц, поддерживаемых платформой .NET, можно найти в описании класса Encoding. Чтобы получить объект кодировки для конкретной кодовой страницы, можно вызвать метод Encoding.GetEncoding(Int32) . Кодовая страница содержит 256 кодовых точек с отсчетом от нуля. В большинстве кодовых страниц кодовые точки от 0 до 127 представляют набор символов ASCII, а кодовые точки от 128 до 255 существенно отличаются у разных кодовых страниц. Например, кодовая страница 1252 предоставляет символы для латинских систем письма, включая английский, немецкий и французский языки. Последние 128 кодовых точек на кодовой странице 1252 содержат диакритические знаки. Кодовая страница 1253 содержит коды символов, которые требуются в греческой системе письма. Последние 128 кодовых точек на кодовой странице 1253 содержат символы греческого языка. Таким образом, в приложении, использующем кодовые страницы ANSI, нельзя хранить греческий и немецкий тексты в одном потоке, если он не содержит идентификатор, указывающий соответствующую кодовую страницу. Двухбайтовые кодировки (DBCS) Поддерживают языки, такие как китайский, японский и корейский, содержащие более 256 символов. В кодировке DBCS каждый символ представлен парой кодовых точек (два байта). Свойство Encoding.IsSingleByte возвращает значение false для двухбайтовых кодировок. Чтобы получить объект кодировки для конкретной кодировки DBCS, можно вызвать метод Encoding.GetEncoding(Int32) . Когда приложение обрабатывает данные DBCS, первый байт символа DBCS (старший байт) обрабатывается в сочетании со вторым байтом, следующим непосредственно за ним. Так как одна пара двухбайтовых кодовых точек может представлять различные символы в зависимости от кодовой страницы, эта схема также не позволяет использовать в одном потоке данных два языка, например японский и китайский.

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

Поддержка кодирования в .NET Core

По умолчанию .NET Core не предоставляет доступ к кодировкам кодовых страниц, кроме кодовой страницы 28591 и кодировок Юникода, например UTF-8 и UTF-16. Но вы можете добавить в свое приложение кодировки кодовых страниц из стандартных приложений Windows, ориентированных на .NET. Дополнительные сведения см. в разделе CodePagesEncodingProvider.

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

Если у вас есть возможность выбрать кодировку для использования в приложении, следует использовать Юникод, предпочтительно UTF8Encoding или UnicodeEncoding. (Также .NET поддерживает третью кодировку Юникода: UTF32Encoding.)

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

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

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

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

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

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

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

В веб-приложении символы, отправленные клиенту в ответ на веб-запрос, должны отражать кодировку, используемую в клиенте. Как правило, требуется задать для свойства HttpResponse.ContentEncoding значение, возвращаемое свойством HttpRequest.ContentEncoding , для отображения текста в той кодировке, которую ожидает пользователь.

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

Кодировщик преобразует строку символов (чаще всего символов Юникода) в их числовой (байтовый) эквивалент. Например, кодировщик ASCII можно использовать для преобразования символов Юникода в 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 для декодирования массива байтов Юникода. В этом примере строка, содержащая несколько символов Юникода, кодируется в файл, а затем два метода декодирования используются для декодирования по десять байтов за раз. Так как замещающая пара оказывается в десятом и одиннадцатом байтах, она декодируется в отдельных вызовах метода. Как видно из выходных данных, метод Encoding.GetString не может правильно декодировать байты и заменяет их символом U+FFFD (замещающим символом). С другой стороны, метод Decoder.GetChars может успешно декодировать массив байтов для получения исходной строки.

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

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

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

Best-Fit Fallback

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

Теоретически все классы кодировок Юникода, доступные в .NET (UTF8Encoding, UnicodeEncoding и UTF32Encoding), поддерживают все символы всех наборов символов, поэтому при их использовании не возникает проблем со стратегией наилучшего соответствия.

Для разных кодовых страниц применяются разные стратегии наилучшего соответствия. Например, для некоторых кодовых страниц полноширинные латинские символы сопоставляются с более распространенными полуширинными символами. Для других кодовых страниц такое сопоставление не выполняется. Даже в случае применения активной стратегии наилучшего соответствия для некоторых символов некоторых кодировок отсутствует возможное сопоставление. Например, для идеографических символов китайского алфавита отсутствуют корректные сопоставления с символами кодовой страницы 1252. В этом случае используются замещающие строки. По умолчанию в качестве замещающей строки используется знак вопроса (U+003F).

Стратегии наилучшего соответствия не документированы подробно. Но для некоторых кодовых страниц их можно найти на веб-сайте Unicode Consortium. Изучите файл readme.txt в предоставленной папке, где описаны правила интерпретации для файлов сопоставления.

В примере ниже используется кодовая страница 1252 (кодовая страница Windows для западноевропейских языков) для иллюстрации стратегии наилучшего соответствия и ее недостатков. Метод Encoding.GetEncoding(Int32) используется для получения объекта кодировки для кодовой страницы 1252. По умолчанию для неподдерживаемых символов Юникода используется стратегия наилучшего соответствия. В примере создается экземпляр строки, содержащий три символа, не относящихся к ASCII (прописная латинская буква S в кружке (U+24C8), надстрочный индекс 5 (U+2075) и знак бесконечности (U+221E)), разделенные пробелами. Как видно из выходных данных примера, при кодировке строки три исходных отличных от пробела символа заменяются вопросительным знаком (U+003F), цифрой пять (U+0035) и цифрой восемь (U+0038). Цифра восемь — особенно неудачная замена неподдерживаемого знака бесконечности, а вопросительный знак показывает, что для исходного символа сопоставление не найдено.

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

Вы также можете реализовать пользовательскую стратегию наилучшего соответствия для кодировки. Дополнительные сведения см. в разделе Implementing a Custom Fallback Strategy .

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

Replacement Fallback

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

В .NET есть классы EncoderReplacementFallback и DecoderReplacementFallback, которые подставляют замещающую строку, если не удается точно сопоставить символ при кодировании или декодировании. По умолчанию эта замещающая строка — вопросительный знак, но вы можете вызвать перегрузку конструктора класса, чтобы выбрать другую строку. Как правило, замещающая строка — это отдельный символ, хотя это необязательно. В примере ниже поведение кодировщика кодовой страницы 1252 изменяется путем создания экземпляра объекта EncoderReplacementFallback , который использует символ звездочки (*) в качестве замещающей строки.

Также можно реализовать класс замены для кодировки. Дополнительные сведения см. в разделе Implementing a Custom Fallback Strategy .

Помимо вопросительного знака (U+003F) в качестве замещающей строки часто используется замещающий символ Юникода (U+FFFD), особенно при декодировании последовательностей байтов, которые не удается преобразовать в символы Юникода. Однако вы можете выбрать любую замещающую строку, в том числе из нескольких символов.

Exception Fallback

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

Вы также можете реализовать пользовательский обработчик исключений для операции кодирования. Дополнительные сведения см. в разделе Implementing a Custom Fallback Strategy .

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

Объект EncoderFallbackException включает метод IsUnknownSurrogate , указывающий, представляют ли символы (или символ), которые не удается закодировать, неизвестную замещающую пару (тогда метод возвращает значение true ) или неизвестный отдельный символ (тогда метод возвращает значение false ). Символы замещающей пары доступны в свойствах EncoderFallbackException.CharUnknownHigh и EncoderFallbackException.CharUnknownLow . Неизвестный отдельный символ доступен в свойстве EncoderFallbackException.CharUnknown . Свойство EncoderFallbackException.Index указывает позицию первого символа, который не удалось закодировать, в строке.

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

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

Implementing a Custom Fallback Strategy

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

— классы EncoderReplacementFallback и EncoderReplacementFallbackBuffer можно использовать для замены символов в операциях кодирования;

— классы DecoderReplacementFallback и DecoderReplacementFallbackBuffer можно использовать для замены символов в операциях декодирования;

— классы EncoderExceptionFallback и EncoderExceptionFallbackBuffer можно использовать для создания исключения EncoderFallbackException , когда символ не удается закодировать;

— классы DecoderExceptionFallback и DecoderExceptionFallbackBuffer можно использовать для создания исключения 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 и DecoderFallbackBuffer , также имеют два закрытых поля экземпляра: точное число символов в буфере и индекс в буфере следующего символа, который нужно вернуть.

Пример EncoderFallback

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

В приведенном коде определяется класс с именем CustomMapper , производный от EncoderFallback , для обработки наилучшего сопоставления символов, отсутствующих в ASCII. Его метод CreateFallbackBuffer возвращает объект CustomMapperFallbackBuffer , предоставляющий реализацию EncoderFallbackBuffer . Класс CustomMapper использует объект Dictionary<TKey,TValue> для хранения сопоставлений неподдерживаемых символов Юникода (значение ключа) и соответствующих им 8-битных символов (которые хранятся в двух последовательных байтах в виде 64-разрядного целого числа). Чтобы это сопоставление было доступно резервному буферу, экземпляр CustomMapper передается в качестве параметра конструктору класса CustomMapperFallbackBuffer . Так как самое длинное сопоставление — это строка INF для символа Юникода с кодом U+221E, свойство MaxCharCount возвращает значение 3.

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

📎📎📎📎📎📎📎📎📎📎