|
|
|||||||||||||||||||||||||||||
|
Delphi и кодировка Unicode, часть II: Новые функции библиотеки RTL и классы для поддержки кодировки UnicodeИсточник: embarcadero
Автор: Виктор Роднев ©Воспроизведение и распространение данной статьи возможно при условии установки прямой ссылки на данный портал В данной статье новые функции библиотеки Tiburon Runtime Library, которые помогают обрабатывать строки Unicode. ВведениеВ части I было показано, какие выгоды дает разработчикам на Delphi поддержка кодировки Unicode, позволяя работать со всеми наборами символов в кодировке Unicode. Были рассмотрены основные особенности типа строки UnicodeString и было показано, как его можно использовать в Delphi. В части II будет рассказано о некоторых новых функциях библиотеки Delphi Runtime Library, предназначенных для поддержки Unicode, и общих методах обработки строк. Класс TCharacterБиблиотека Tiburon RTL включает новый класс TCharacter, который описывается в модуле Character. Это закрытый класс, который полностью состоит из статичных функций класса. Разработчикам не следует создавать экземпляры класса TCharacter, предпочтительнее просто вызывать его статические методы класса напрямую. Функции этого класса позволяют, в числе прочего, выполнять:
Классом TCharacter используются стандарты, установленные организацией Unicode consortium. Разработчики могут использовать класс TCharacter для выполнения многих действий, выполнявшихся до этого с наборами символов. Например, следующий программный код: uses Character; begin if MyChar in ["a"..."z", "A"..."Z"] then begin ... end; end; можно легко заменить кодом: uses Character; begin if TCharacter.IsLetter(MyChar) then begin ... end; end; Модуль Character содержит также ряд автономных функций, которые выполняют функции каждой из функций класса TCharacter, так что если предпочтительнее простой вызов функции, приведенный выше программный код можно переписать как: uses Character; begin if IsLetter(MyChar) then begin ... end; end; Таким образом, класс TCharacter можно использовать для выполнения многих действий или проверки символов, которая может понадобиться. Кроме того, класс TCharacter содержит методы класса, позволяющие определить, является ли символ верхним или нижним суррогатом суррогатной пары. Класс TEncodingБиблиотека Tiburon RTL также включает новый класс TEncoding. Его назначение - определить конкретный тип кодировки символов, чтобы можно было сообщить библиотеке VCL, какой тип кодировки необходимо использовать в конкретных ситуациях. Например, пусть есть экземпляр TStringList, содержащий текст, который необходимо записать в файл. Ранее необходимо было бы написать begin ... MyStringList.SaveToFile("SomeFilename.txt"); ... end; и файл записался бы, по умолчанию, в кодировке ANSI. Данный код по-прежнему хорошо работает - файл запишется им в кодировке ANSI, как и раньше, но теперь, когда в Delphi поддерживаются строковые данные в кодировке Unicode, разработчикам может потребоваться записать строковые данные в какой-либо конкретной кодировке. Поэтому оператор SaveToFile (а также LoadFromFile) теперь имеет дополнительный второй параметр, которым определяется используемая кодировка: begin ... MyStringList.SaveToFile("SomeFilename.txt", TEncoding.Unicode); ... end; При выполнении приведенного выше кода файл будет записан как текстовый файл в кодировке Unicode (UTF-16). Классом TEncoding будет также преобразовываться заданный набор байтов из одной кодировки в другую, извлекаться информация о байтах и/или символах в заданной строке или массиве символов, преобразовываться любая строка в массив array of byte (TBytes) и выполняться другие функции, которые могут потребоваться для конкретной кодировки заданной строки или заданного массива символов. Класс TEncoding включает следующие свойства класса, дающие доступ к экземпляру TEncoding заданной кодировки: class property ASCII: TEncoding read GetASCII; class property BigEndianUnicode: TEncoding read GetBigEndianUnicode; class property Default: TEncoding read GetDefault; class property Unicode: TEncoding read GetUnicode; class property UTF7: TEncoding read GetUTF7; class property UTF8: TEncoding read GetUTF8; Свойство Default ссылается на активную кодовую страницу ANSI. Свойство Unicode ссылается на UTF-16. Класс TEncoding также включает функцию class function TEncoding.GetEncoding(CodePage: Integer): TEncoding; которая будет возвращать экземпляр TEncoding, соответствующий кодовой странице, переданной в параметре. Кроме того, он включает следующую функцию: function GetPreamble: TBytes; которая будет возвращать правильный маркер порядка байтов для заданной кодировки. Класс TEncoding также представляет собой интерфейс, совместимый с классом .Net Encoding. TStringBuilderБиблиотека RTL теперь включает класс TStringBuilder. Его назначение ясно из его названия - это класс, предназначенный для создания строк. Класс TStringBuilder содержит большое количество перегружаемых функций для добавления, замены и вставки содержимого в заданную строку. Этот класс упрощает создание единых строк из множества различных типов данных. Каждая из функций Append, Insert и Replace возвращает экземпляр класса TStringBuilder, поэтому их можно легко объединять для создания единой строки. Например, можно использовать класс TStringBuilder вместо усложненного оператора Format. Например, можно написать следующий программный код: procedure TForm86.Button2Click(Sender: TObject); var MyStringBuilder: TStringBuilder; Price: double; begin MyStringBuilder := TStringBuilder.Create(''); try Price := 1.49; Label1.Caption := MyStringBuilder.Append('The apples are $').Append(Price). ÄAppend(' a pound.').ToString; finally MyStringBuilder.Free; end; end; Класс TStringBuilder также представляет собой интерфейс, совместимый с классом .Net StringBuilder. Объявление новых типов строк Компилятор Tiburon позволяет объявить собственный тип строки, связанный с заданной кодовой страницей. Доступно любое число кодовых страниц. Например, если необходим тип строки, соответствующий кодировке ANSI-кириллице, можно объявить: type // Кодовая страница для ANSI-кириллицы - 1251 CyrillicString = type Ansistring(1251); И новый тип строки будет соответствовать кодовой странице кириллицы. Дополнительная поддержка Unicodeбиблиотекой RTLВ библиотеку RTL добавлен ряд подпрограмм, которыми поддерживается использование строк Unicode. StringElementSizeПодпрограммой StringElementSize возвращается типичный размер элемента (элемента кода) в заданной строке. Рассмотрим следующий код: procedure TForm88.Button3Click(Sender: TObject); var A: AnsiString; U: UnicodeString; begin A := 'This is an AnsiString'; Memo1.Lines.Add('The ElementSize for an AnsiString is: ' + IntToStr(StringElementSize(A))); U := 'This is a UnicodeString'; Memo1.Lines.Add('The ElementSize for an UnicodeString is: ' + IntToStr(StringElementSize(U))); end; Результатом выполнения приведенного выше кода будет: The ElementSize for an AnsiString is: 1 The ElementSize for an UnicodeString is: 2 StringCodePageПодпрограммой StringCodePage будет возвращаться значение Word, которое соответствует кодовой странице для заданной строки. Рассмотрим следующий код: procedure TForm88.Button2Click(Sender: TObject); type // Кодовая страница для ANSI-кириллицы - 1251 CyrillicString = type AnsiString(1251); var A: AnsiString; U: UnicodeString; U8: UTF8String; C: CyrillicString; begin A := 'This is an AnsiString'; Memo1.Lines.Add('AnsiString Codepage: ' + IntToStr(StringCodePage(A))); U := 'This is a UnicodeString'; Memo1.Lines.Add('UnicodeString Codepage: ' + IntToStr(StringCodePage(U))); U8 := 'This is a UTF8string'; Memo1.Lines.Add('UTF8string Codepage: ' + IntToStr(StringCodePage(U8))); C := 'This is a CyrillicString'; Memo1.Lines.Add('CyrillicString Codepage: ' + IntToStr(StringCodePage(C))); end; Результатом выполнения приведенного выше кода будет: The Codepage for an AnsiString is: 1252 The Codepage for an UnicodeString is: 1200 The Codepage for an UTF8string is: 65001 The Codepage for an CyrillicString is: 1251 Другие функции библиотеки RTL, связанные с кодировкой UnicodeЕсть ряд других подпрограмм для преобразования строк из одной кодовой страницы в другую. В их числе: UnicodeStringToUCS4String UCS4StringToUnicodeString UnicodeToUtf8 Utf8ToUnicode Кроме того, в библиотеке RTL также появился тип RawByteString, который представляет собой тип строки, не связанный ни с какой кодировкой: RawByteString = type AnsiString($FFFF); Тип RawByteString позволяет передавать строковые данные для любой кодовой страницы без каких-либо преобразований последней. Он особенно полезен для подпрограмм, для которых кодировка не имеет значения, например для побайтового поиска в строке. Обычно это означает, что параметры подпрограмм, которыми обрабатываются строки без связи с их кодовыми страницами, должны иметь тип RawByteString. Тип RawByteString следует присваивать переменным как можно реже, если вообще когда-либо, так как это может привести к непредсказуемому поведению и возможной потере данных. Как правило, присвоения типов строк совместимы друг с другом. Например, присвоение MyUnicodeString := MyAnsiString; будет выполнено, как и ожидалось - содержимое строки типа AnsiString будет помещено в строку типа UnicodeString. Как правило, можно присваивать один тип строки строке другого типа, и компилятор выполнит необходимые преобразования, если возможно. Однако некоторые преобразования могут привести к потере данных, и необходимо остерегаться при перемещении из строки одного типа, которая включает данные в кодировке Unicode, в другую, тип которой не поддерживает Unicode. Например, можно присваивать тип UnicodeString строке типа AnsiString, но если строка типа UnicodeString содержит символы, которые не отображаются в активной в данный момент кодовой странице ANSI, то эти символы будут потеряны при преобразовании. Рассмотрим следующий код: procedure TForm88.Button4Click(Sender: TObject); var U: UnicodeString; A: AnsiString; begin U := 'This is a UnicodeString'; A := U; Memo1.Lines.Add(A); U := 'Добро пожаловать в мир Юникода с использованием Дельфи 2009!!'; A := U; Memo1.Lines.Add(A); end; Результат выполнения этого кода, если текущая кодовая страница ОС - 1252, будет следующим: This is a UnicodeString ????? ?????????? ? ??? ??????? ? ?????????????? ?????? 2009!! Как можно видеть, при назначении типа UnicodeString строке типа AnsiString информация теряется, так как символы кириллицы не отображаются кодовой страницей Windows-1252. Причина такого результата - строка UnicodeString содержала символы, не представимые в кодовой странице AnsiString, эти символы были потеряны и заменены вопросительными знаками при назначении типа UnicodeString строке типа AnsiString. SetCodePageФункция SetCodePage, объявленная в модуле System.pas как procedure SetCodePage(var S: AnsiString; CodePage: Word; Convert: Boolean); представляет собой новую функцию RTL, которой задается новая кодовая страница для строки типа AnsiString. Необязательным параметром Convert определяется, следует ли преобразовать сами данные строки в заданную кодовую страницу. Если значение параметра Convert - False, то для строки просто будет изменена кодовая страница. Если значение параметра Convert - True, то данные передаваемой строки будут преобразованы в заданную кодовую страницу. Функция SetCodePage должна использоваться редко и с большой осторожностью. Обратите внимание, что, если кодовая страница не соответствует существующим данным строки (то есть значение параметра Convert - False), то результаты могут оказаться непредсказуемыми. Кроме того, если существующие данные строки преобразованы, а в новой кодовой странице не представлен заданный исходный символ, данные могут потеряться. Получение массива байтов TBytesиз строкВ составе библиотеки RTL есть также набор перегружаемых подпрограмм для извлечения из строки массива байтов. Как будет показано в части III, рекомендуется использовать в качестве буфера данных массив TBytes, а не строку. Библиотека RTL упрощает это за счет перегружаемых версий функции BytesOf(), принимающей в качестве параметра разные типы строк. ЗаключениеБиблиотека Tiburon"s Runtime Library теперь полностью поддерживает новый тип строки UnicodeString. В нее входят новые классы и подпрограммы для обработки и преобразования строк в кодировке Unicode, для управления кодовыми страницами и для упрощения перехода с более ранних версий. В части III будут рассмотрены специальные кодовые конструкции, которые необходимы, чтобы выяснить: готов ли тот или иной программный код к переходу на кодировку Unicode. Ссылки по теме
|
|