Кратко съдържание



страница67/73
Дата22.08.2016
Размер8.56 Mb.
#7053
1   ...   63   64   65   66   67   68   69   70   ...   73

Кодиращи схеми


При преноса на текстове по мрежата или записа им във файлове се използват т. нар. кодиращи схеми (encodings). Най-често се използват кодиращите схеми от стандарта UTF (Unicode Transformation Format), дефинирани от Unicode стандартите.

Кодиращи схеми UTF


UTF представляват алгоритмични кодиращи схеми, при които всеки Unicode номер се представя като уникална поредица от 8-битови, 16-битови или 32-битови стойности. От тук произлизат и различните формати за съхранение на текст в Unicode формат в компютърната памет - UTF-8, UTF-16, UTF-32.

Най-разпространеният в Интернет е UTF-8. UTF-16 се използва в Windows и Java, а UTF-32 е популярен в някои UNIX системи. Конвертирането между различните кодиращи схеми се осъществява от бързи алгоритми, работещи без загуба на информация.

Понеже кодирането при UTF схемите е без загуба, съществува взаимо­еднозначно съответствие между схемите UTF-8, UTF-16 и UTF-32. Това означава, че всеки текст от UTF-8 може да се преобразува до UTF-16 и след това ако се преобразува обратно до UTF-8, ще се получи оригинал­ният UTF-8 текст без никакви промени. Съществуват и други кодиращи схеми, които работят със загуба, и при тях няма взаимоеднозначно съот­ветствие между оригинален текст и кодиран текст.

UTF-8


При UTF-8 символите се кодират с 8-битови стойности, като символите с номера до 128 (т. е. ASCII символите) се представят със собствения си Unicode номер, като най-старшият им бит е нула. Останалите символи се кодират с два, три или четири байта по определени правила. Това кодиране се използва за предаване на текст, когато е необходим компресиран запис. UTF-8 кодирането е подходящо за текстове, в които преобладават символите от ASCII табли­цата, например за текстове на английски език.

При UTF-8 знаците \u0000 до \u007F се записват с един байт. Това са ASCII символите, използвани в САЩ. Знаците \u0080-\u07FF, които отго­варят на символите от европейските, арабските и еврейските езици, се записват с два байта. Знаците в интервала \u0800-\uFFFF се записват с три байта. Всички останали се записват с четири байта.

За източноазиатските езици кодирането UTF-8 е неефективно, защото записва повечето символи с 4 байта.

UTF-16


Кодиращата схема UTF-16 представя един знак (графема) като една или две 16-битови стойности, като по-често използваните Unicode знаци се предста­вят с една 16-битова стой­ност, а останалите – с две (чрез кодова двойка).

Всички символни низове в .NET Framework инстанциите на класа System. String) съхраняват своите стойности в па­метта в кодиране UTF-16.

UTF-16 е най-ефективният начин за представяне на азиатски символни низове. При ASCII символите UTF-16 схемата не е много ефективна, защо­то се използват по два байта за знак, който може да бъде представен само с един байт.

При UTF-16 трябва да се съобрази правилно и подредбата на байтовете, тъй като се срещат два различни подхода при запис. В зависимост дали подредбата на байтовете е little-endian или big-endian стойността \uABCD се записва съответно като 0xCD 0xAB или като 0xAB 0xCD.


UTF-32


Както предполага наименованието, в тази кодираща схема се използват 32 бита за всеки Unicode знак. Така всеки един символ се записва като 4-байтово число. В повечето приложения не се налага да използвате нещо повече от ASCII символите и в този случай използването на 32 бита е доста разто­чително. Затова употребата на UTF-32 е нежелателна при съхранение на диска или при пренос по мрежата.

Подредба на байтовете при UTF-16 и UTF-32


Броят на байтовете не определя еднозначно кодирането на симво­лите. Съществуват различни начини за подреждане на последовател­ността от байтове. Когато първо се записва най-старшият байт, това е big-endian кодиране, а когато той е в края на записа - little-endian. Преди да предадете между два компютъра например една 4-байтова стойност (UTF-32), трябва да се уверите, че те интерпретират по един и същ начин пос­ле­дователността от байтове.

Unicode разрешава проблема с подредбата на байтовете, като дефинира специален символ с номер U+FFFE, който се нарича "Byte Order Mark (BOM)" и се поставя като идентификатор в началото на Unicode тексто­вете. Наличието на U+FFFE в началото на даден UTF-16 файл указва обратен ред на байтове.

Следната таблица показва съдържанието на BOM в различните видове кодиране:


Байтове

Формат на кодиране

00 00 FE FF

UTF-32, big-endian

FF FE 00 00

UTF-32, little-endian

FE FF

UTF-16, big-endian

FF FE

UTF-16, little-endian

EF BB BF

UTF-8

Знаейки че .NET Framework използва кодиране UTF-16 със запис в little-endian формат, можем да проверим коректната стойност на BOM.

Съществуват и други схеми, производни на UTF-16 и UTF-32. Unicode дефинира стандартите UTF-16BE, UTF-16LE, UTF-32LE и UTF-32BE (big-endian, little- endian), които имат гарантирана подредба на байтовете.


Други кодиращи схеми


Освен изброените Unicode кодиращи схеми има и други такива. Повечето от тях коди­рат Unicode текстовете със загуба. Това означава, че няма взаимоеднозначно съответствие между оригиналния текст и кодирания текст, т. е. от оригиналния текст можем да получим кодирания текст, но обратната операция не е еднозначна.

Например ASCII кодирането преобразува всички Unicode символи с кодове в диапазона \u0000-\u007F в съответен ASCII символ, а останалите в символа "?" (0x3F). Всички символи от кирилицата при това кодиране се заместват с "?" и губят оригиналната си стойност.

Кодиращата схема Windows-1251 замества ASCII символите, символите от кирилицата и някои други с байтове в диапазона 0x00-0xFF, а останалите замества със знак "?" (0x3F). Тази кодираща схема често пъти се изпол­зва за представяне на текстове на кирилица, но тя не е универсална, както UTF-8 и причинява загуби при някои текстове.

Кодиращи схеми – пример


За илюстрация на разгледаните кодиращи схеми са дадени няколко сим­вола, техните Unicode номера и кодирането им в различните UTF схеми:

Знак

Unicode номер

Unicode номер (hex)

UTF-8

(hex)

UTF-16

(hex)

UTF-32

(hex)

A

главна латинска буква "A"



65

U+0041

0x41

0x0041

0x00000041

математичес­ки символ "две трети"



8532

U+2154

0xE2 0x85 0x94

0x2154

0x00002154

символ "сърце"



9829

U+2665

0xE2 0x99 0xA5

0x2665

0x00002665

листо на китайски



33865

U+8449

0xE8 0x91 0x89

0x8449

0x00008449

нота шестнай­сетина



119137

U+1D161

0xF0 0x9D 0x85 0xA1

0xD834 0xDD61

0x0001D161

За да конвертираме текст от символи в байтове и обратно, можем да използваме класа System.Text.Encoding.

Конвертиране със System.Text.Encoding


Когато съхраняваме текстова информация на диск или я предаваме по мрежата, тя трябва да бъде представена като поредица от байтове. Когато искаме да прочетем същата тази информация, трябва отново да я преоб­разуваме в текст. Тези операции са пример за случаи, когато имаме нужда от конвертиране между символи и тяхното байтово представяне в различ­ните разгледани кодиращи схеми.

В .NET Framework преобразуването на текст в последователност от бай­тове и обратното по дадена кодираща схема можем да извършваме с помощта на класа System.Text.Encoding и неговите наследници.

В таблицата са дадени най-често използваните методи и свойства на класа Encoding:

Метод/Свойство

Описание

GetBytes(string)

Конвертира символен низ в масив от байтове.

GetString(byte[])

Конвертира масив от байтове в символен низ.

GetChars(byte[])

Конвертира масив от байтове в масив от символи.

GetMaxByteCount(…)

GetMaxCharCount(…)

Връща максималната дължина на резултата, която може да се получи при конвертиране.

Convert(Encoding, Encoding, byte[])

Конвертира от една схема на кодиране в друга.

Следват няколко примера, които илюстрират използването на тези методи за конвертиране между различните кодиращи схеми:

Encoding utf16le = Encoding.Unicode;

byte[] bytes = utf16le.GetBytes("\uABCD");

Console.WriteLine("0x{0:X} 0x{1:X}", bytes[0], bytes[1]);

// Result: 0xCD 0xAB


Encoding utf16be = Encoding.BigEndianUnicode;

bytes = utf16be.GetBytes("\uABCD");

Console.WriteLine("0x{0:X} 0x{1:X}", bytes[0], bytes[1]);

// Result: 0xAB 0xCD


Encoding windows1251 = Encoding.GetEncoding("windows-1251");

bytes = windows1251.GetBytes("Цакам с A♥ и две ♣.");

Console.WriteLine(BitConverter.ToString(bytes));

// Result: D6-E0-EA-E0-EC-20-F1-20-41-A6-20-E8-20-E4-E2-

// E5-20-A6-2E
Console.WriteLine(windows1251.GetString(bytes));

// Result: Цакам с A│ и две │.

// Windows-1251 encoding is unable to preserve

// some character's original values


Encoding utf8 = Encoding.UTF8;

bytes = utf8.GetBytes("Ω(x) ≤ Ψ(x)π² ≤ ∫φ(x) ∂x ≤ ⅔");

Console.WriteLine(BitConverter.ToString(bytes));

// Result: CE-A9-28-78-29-20-E2-89-A4-20-CE-A8-28-78-

// 29-CF-80-C2-B2-20-E2-89-A4-20-E2-88-AB-CF-86-28-78-29-

// 20-E2-88-82-78-20-E2-89-A4-20-E2-85-94


Encoding ascii = Encoding.ASCII;

bytes = ascii.GetBytes("© 2004 Mente®");

Console.WriteLine(BitConverter.ToString(bytes));

// Result: 3F-20-32-30-30-34-20-4D-65-6E-74-65-3F


Console.WriteLine(ascii.GetString(bytes));

// Result: ? 2004 Mente?

// ASCII encoding is unable to preserve

// some character's original values


Encoding western = Encoding.GetEncoding("iso-8859-1");

bytes = western.GetBytes("© 2004 Mente®");

Console.WriteLine(BitConverter.ToString(bytes));

// Result: A9-20-32-30-30-34-20-4D-65-6E-74-65-AE


Console.WriteLine(western.GetString(bytes));

// Result: c 2004 MenteR

// ISO-8859-1 (latin) encoding is unable to preserve

// some character's original values



В разгледания пример първо създаваме обект от тип Encode.Unicode. След това извикваме метода му GetBytes(string) и запазваме върнатия резултат в масив от байтове. Отпечатваме получения масив от байтове на екрана, като задаваме формат за шестнайсетично число.

Вторият пример е аналогичен но вместо Unicode кодираща схема изпол­зваме BigEndianUnicode, за да укажем, че искаме запис, при който по-старшите байтове се записват преди младшите.

В третия пример създаваме Encoding обект с конструктора GetEncoding(), като му подаваме като параметър името на кодиращата схема windows-1251. Отново с помощта на GetBytes(string) взимаме байтовото предста­вяне на низа и с помощта на класа BitConverter го отпечатваме на екрана. Класът BitConverter е предназначен за преобразуване на базови типове (числа, знаци, низове, булеви стойности) в редици от байтове и обратно. В случая използваме метода му ToString(byte[]) за да преобра­зуваме поредицата във вид, удобен за визуализация.

Следващата стъпка демонстрира как да получим обратно символният низ от извлечената поредица от байтове по зададена кодираща схема.

Останалите примери аналогично изпол­зват операциите GetBytes(string) и GetString(bytes[]) за UTF8, ASCII и ISO-8859-1. Вижда се, че при някои кодирания преобразуванията са със загуба.

Кодиране Base64


Когато се налага да се пренесат двоични данни през текстова среда, която поддържа само 7-битово кодиране, нап­ример при изпращане на ZIP архив по имейл, се налага последовател­ността от байтове да се представи като символен низ. Тази задача се изпълнява най-често с помощта на кодирането Base64.

Кодиращата схема Base64 преобразува всеки три последователни байта в четири символа измежду A-Z, a-z, + и /. В резултат на това кодиране обемът на данните се увеличава с около 1/3.

За да извършим преобразуване на последователност от байтове в Base64 низ в .NET Framework можем да използваме класа System.Convert. Мето­дът Convert.ToBase64String(byte[]) приема като параметър масива от байтове и по гореописания начин го преобразува в низ.

За преобразуване в обратна посока, от Base64 низ към масив от байтове, се използва методът Convert.FromBase64String(base64string). Този ме­тод връща като резултат получения масив от байтове. Тази операция се налага да бъде извършвана например когато се записва прикачен към e-mail файл на твърдия диск.

Следният пример показва и двете преобразуващи операции:

using System;
class Base64Demo

{

static void Main()



{

byte[] array = {0x00, 0x3D, 0x80, 0xA0, 0xFF};


string base64 = Convert.ToBase64String(array);

Console.WriteLine(base64);

// Result: AD2AoP8=
byte[] array2 = Convert.FromBase64String(base64);

Console.WriteLine(BitConverter.ToString(array2));

// Result: 00-3D-80-A0-FF

}

}


Работа с Unicode във Visual Studio.NET


Различните схеми за кодиране за запис на файлове на компютъра важат както за всички текстови файлове така и за файловете със сорс код във Visual Studio.NET. Текстовият редактор има възможност за работа с фай­лове, записани в голям набор от кодирания.

Ако не укажем изрично каква кодираща схема да се използва, текстовият редактор на Visual Studio.NET използва кодирането по подразбиране в Windows. За да използваме Unicode символи в сорс кода на програмите си, трябва да запишем файловете си с кодираща схема UTF-8.


Поддръжка на всички езици


По подразбиране Windows не поддържа всички езици от Unicode стан­дарта. С цел спестяване на дисково пространство и други ресурс в Microsoft Windows шрифтовете за източно­азиатските езици не се инста­лират по подразбиране, но могат да се инста­лират ръчно.

Това става като в Control Panel от настройките на Regional and Language Options, както се вижда на фигурата:




Използване на Unicode в редактора на Visual Studio .NET – пример


С настоящия пример ще разгледаме нагледно как чрез редактора на Visual Studio .NET можем да създаваме, компилираме и изпълняваме програми, които съдържат в сорс кода си Unicode низове.

Ето стъпките за изграждането на проект съдържащ Unicode низове:



  1. Стартираме VS.NET

  2. Създаваме ново конзолно приложение на езика C#

  3. Заместваме кода в главния файл (Class1.cs) със следния код:

using System;

using System.Text;

using System.Windows.Forms;
class UnicodeInVsNETDemo

{

static void Main()



{

StringBuilder sb = new StringBuilder();

sb.Append("What is Unicode? (English)");

sb.Append(Environment.NewLine);

sb.Append("Какво е Unicode? (Bulgarian)");

sb.Append(Environment.NewLine);

sb.Append("Qu'est ce qu'Unicode? (French)");

sb.Append(Environment.NewLine);

sb.Append("Was ist Unicode? (German)");

sb.Append(Environment.NewLine);

sb.Append("¿Qué es Unicode? (Spanish)");

sb.Append(Environment.NewLine);

sb.Append("Cos'è Unicode? (Italian)");

sb.Append(Environment.NewLine);

sb.Append("Что такое Unicode? (Russian)");

sb.Append(Environment.NewLine);

sb.Append("Τι είναι το Unicode? (Greek)");

sb.Append(Environment.NewLine);

sb.Append("Mikä on Unicode? (Finnish)");

sb.Append(Environment.NewLine);

sb.Append("Što je Unicode? (Croatian)");

sb.Append(Environment.NewLine);

sb.Append("Hvað er Unicode? (Icelandic)");

sb.Append(Environment.NewLine);

sb.Append("ユニコードとは何か? (Japanese)");

sb.Append(Environment.NewLine);

sb.Append("유니코드에 대해? (Korean)");

sb.Append(Environment.NewLine);

sb.Append("什麽是Unicode(統一碼/標準萬國碼)? (Traditional Chinese)");

sb.Append(Environment.NewLine);

sb.Append("什么是Unicode(统一码)? (Simplified Chinese)");

sb.Append(Environment.NewLine);

sb.Append("ما هي الشفرة الموحدة \"يونِكود\" ؟ (Arabic)");

sb.Append(Environment.NewLine);

sb.Append("რა არის უნიკოდი? (Georgian)");

sb.Append(Environment.NewLine);

sb.Append("מה זה יוניקוד (Unicode)? (Hebrew)");

sb.Append(Environment.NewLine);

sb.Append("يونی‌کُد چيست؟ (Persian)");

sb.Append(Environment.NewLine);

sb.Append("Unicode คืออะไร? (Thai)");

sb.Append(Environment.NewLine);

sb.Append("Unicode là gì? (Vietnamese)");

sb.Append(Environment.NewLine);

sb.Append("यूनिकोड क्या है? (Hindi)");

string s = sb.ToString();

MessageBox.Show(s, "Unicode Demo");

}

}



Ето как изглежда главният екран на VS.NET:



  1. Сега да запишем Class1.cs с кодиране UTF-8. Това става по следния начин: File | Save Class1.cs As... | Save with encoding… | Unicode (UTF-8 with signature) - Codepage 65001.





  1. Опитваме да компилираме проекта. Получаваме съобщение за грешка, тъй като компилаторът се опитва да намери пространството от имена System.Windows.Forms но не може, защото то не е налич­но по подразбиране в конзолни приложения.

  2. Ако компилацията е била неуспешна, добавяме референция в проекта към System.Windows.Forms.dll. Това може да стане по следния начин: Project | Add Reference... | System.Windows. Forms.dll | Select | OK.

  3. Компилираме. Компилацията вече минава успешно.

  4. Изпълняваме програмата с [F5]. На екрана виждаме прозорец със съобщение, в което се извеждат зададените Unicode сим­воли:



  1. Ако някои от съобщенията не излизат правилно (например вместо буквите се появяват квадратчета), това се дължи на липсата на поддръжка на някои азиатски шрифтове в текущата инсталация на Windows. Проблемът може да се реши като се инсталират липсва­щите шрифтове от Regional Options в контролния панел на Windows.



Сподели с приятели:
1   ...   63   64   65   66   67   68   69   70   ...   73




©obuch.info 2024
отнасят до администрацията

    Начална страница