Delphi та кодування Unicode, частина II: Нові функції бібліотеки RTL і класи для підтримки кодування Unicode, Різне, Програмування, статті

Автор: Віктор Рідні ©

Відтворення та поширення даної статті можливе за умови встановлення прямого посилання на даний портал


В даній статті нові функції бібліотеки 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.

Схожі статті:


Сподобалася стаття? Ви можете залишити відгук або підписатися на RSS , щоб автоматично отримувати інформацію про нові статтях.

Коментарів поки що немає.

Ваш отзыв

Поділ на параграфи відбувається автоматично, адреса електронної пошти ніколи не буде опублікований, допустимий HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

*