Преобразование символов в UTF-8 ?
От: Cynic Россия  
Дата: 22.03.11 12:04
Оценка:
Столкнулся со странным поведение метода Encoding.GetChars:
byte[] utf8CharsCode = new [] { 237, 160, 130 }; //0xEDA082 == UTF8+D802
char[] utf8Chars = Encoding.UTF8.GetChars(utf8CharsCode);

Console.WriteLine(utf8Chars.Count);
for(int i = 0; i< utf8Chars.Count; i++)
   Console.WriteLine("{0}-й байт : {1}", i + 1,(int)utf8Chars[i]);

/* 
*  Вывод в консоль:
*  1-й байт : 65213
*  2-й байт : 65215
*/

Хотя символ UTF8 с кодом 0xEDA082 существует, но метод вместо него выкидывает непонятный массив символов со странными значениями. С чего бы это
:)
Re: Преобразование символов в UTF-8 ?
От: vmpire Россия  
Дата: 22.03.11 13:10
Оценка:
Здравствуйте, Cynic, Вы писали:

C>Столкнулся со странным поведение метода Encoding.GetChars:

C>
C>byte[] utf8CharsCode = new [] { 237, 160, 130 }; //0xEDA082 == UTF8+D802
C>char[] utf8Chars = Encoding.UTF8.GetChars(utf8CharsCode);

C>Console.WriteLine(utf8Chars.Count);
C>for(int i = 0; i< utf8Chars.Count; i++)
C>   Console.WriteLine("{0}-й байт : {1}", i + 1,(int)utf8Chars[i]);

C>/* 
C>*  Вывод в консоль:
C>*  1-й байт : 65213
C>*  2-й байт : 65215
C>*/
C>

C>Хотя символ UTF8 с кодом 0xEDA082 существует, но метод вместо него выкидывает непонятный массив символов со странными значениями. С чего бы это
И что это за символ? Что за код D802?

Вы для начала сделайте компилящийся пример, разберитесь с типами данных (например, конвертация в выводе в консоль бессмысленна), а потом возвращайтесь.
Кстати, текстовые редакторы при разборе этих кодов также возвращают два символа.
Re: Преобразование символов в UTF-8 ?
От: hattab  
Дата: 22.03.11 13:37
Оценка:
Здравствуйте, Cynic, Вы писали:

C> Столкнулся со странным поведение метода Encoding.GetChars:

C>
C> byte[] utf8CharsCode = new [] { 237, 160, 130 }; //0xEDA082 == UTF8+D802
C> char[] utf8Chars = Encoding.UTF8.GetChars(utf8CharsCode);

C> Console.WriteLine(utf8Chars.Count);
C> for(int i = 0; i< utf8Chars.Count; i++)
C>    Console.WriteLine("{0}-й байт : {1}", i + 1,(int)utf8Chars[i]);

C> /*
C> *  Вывод в консоль:
C> *  1-й байт : 65213
C> *  2-й байт : 65215
C> */
C>

C> Хотя символ UTF8 с кодом 0xEDA082 существует, но метод вместо него выкидывает непонятный массив символов со странными значениями. С чего бы это

Во-первых нет никаких символов UTF8. UTF-8 это способ преобразования юникод-кодпоинтов в последовательности байтов. Во-вторых, приведенная последовательность (237, 160, 130) некорректна т.к. после байта-маркера начала последовательности (ED) должен следовать байт со значением в диапазоне 80 — 9F (128 — 159). В-третьих нет ничего удивительно в том, что GetChars для одного юникод-кодпоинта вернет два символа т.к. supplementary-диапазон юникода ( > FFFF) представляется в UTF-16 (а виндовый юникод всегда представлен в UTF-16) в виде суррогатной пары.
avalon 1.0rc3 rev 380, zlib 1.2.3
Re[2]: Преобразование символов в UTF-8 ?
От: Cynic Россия  
Дата: 22.03.11 13:53
Оценка:
Здравствуйте, vmpire, Вы писали:

V>Здравствуйте, Cynic, Вы писали:


C>>Столкнулся со странным поведение метода Encoding.GetChars:

C>>
C>>byte[] utf8CharsCode = new [] { 237, 160, 130 }; //0xEDA082 == UTF8+D802
C>>char[] utf8Chars = Encoding.UTF8.GetChars(utf8CharsCode);

C>>Console.WriteLine(utf8Chars.Count);
C>>for(int i = 0; i< utf8Chars.Count; i++)
C>>   Console.WriteLine("{0}-й байт : {1}", i + 1,(int)utf8Chars[i]);

C>>/* 
C>>*  Вывод в консоль:
C>>*  1-й байт : 65213
C>>*  2-й байт : 65215
C>>*/
C>>

C>>Хотя символ UTF8 с кодом 0xEDA082 существует, но метод вместо него выкидывает непонятный массив символов со странными значениями. С чего бы это

V>И что это за символ? Что за код D802?

Этот код не используется: U+D802 � ed a0 82 здесь

V>Вы для начала сделайте компилящийся пример, разберитесь с типами данных (например, конвертация в выводе в консоль бессмысленна), а потом возвращайтесь.

В каком месте они у вас не компиляться? Студии под рукой нет, набирал по памяти, возможно поэтому и косяки Да и какая разница если методу передаётся допустимый код UTF8? Метод должен либо выкинуть исключение, либо вернуть значение указывающее, что символ не существует!

V>Кстати, текстовые редакторы при разборе этих кодов также возвращают два символа.

Например.
:)
Re[3]: Преобразование символов в UTF-8 ?
От: vmpire Россия  
Дата: 22.03.11 14:51
Оценка:
Здравствуйте, Cynic, Вы писали:

V>>И что это за символ? Что за код D802?

C>Этот код не используется: U+D802 � ed a0 82 здесь
Так это первый символ суррогатной пары. Вот парсер и пытается сделать пару символов.

V>>Вы для начала сделайте компилящийся пример, разберитесь с типами данных (например, конвертация в выводе в консоль бессмысленна), а потом возвращайтесь.

C>В каком месте они у вас не компиляться? Студии под рукой нет, набирал по памяти, возможно поэтому и косяки Да и какая разница если методу передаётся допустимый код UTF8? Метод должен либо выкинуть исключение, либо вернуть значение указывающее, что символ не существует!
В нескольких местах. Но это сейчас не так важно

V>>Кстати, текстовые редакторы при разборе этих кодов также возвращают два символа.

C>Например.
Notepad
Re[2]: Преобразование символов в UTF-8 ?
От: Cynic Россия  
Дата: 22.03.11 14:55
Оценка:
Здравствуйте, hattab, Вы писали:

H>Во-первых нет никаких символов UTF8. UTF-8 это способ преобразования юникод-кодпоинтов в последовательности байтов.

Угу. Это я так для краткости.

H>Во-вторых, приведенная последовательность (237, 160, 130) некорректна т.к. после байта-маркера начала последовательности (ED) должен следовать байт со значением в диапазоне 80 — 9F (128 — 159).


Символ с кодом 0xEDA082 имеет двоичное представление 11101101 10100000 10000010, что соответствует кодировке UTF-8. Кроме того после ED следует код A0, который лежит в указанном вами диапазоне 80 — 9F. Правда я не понимаю почему байт после байта маркера должен иметь значения именно в диапазоне 80 — 9F, т.к. если учесть, что этот байт кодируется как 10xxxxxx, то он может принимать значения от 10000000 до 10111111, т.е. диапазон будет 80-BF.

H>В-третьих нет ничего удивительно в том, что GetChars для одного юникод-кодпоинта вернет два символа т.к. supplementary-диапазон юникода ( > FFFF) представляется в UTF-16 (а виндовый юникод всегда представлен в UTF-16) в виде суррогатной пары.


Вот тут поподробнее я ни чего не понял
:)
Re[3]: Преобразование символов в UTF-8 ?
От: hattab  
Дата: 22.03.11 16:20
Оценка: 3 (1)
Здравствуйте, Cynic, Вы писали:

C> H>Во-вторых, приведенная последовательность (237, 160, 130) некорректна т.к. после байта-маркера начала последовательности (ED) должен следовать байт со значением в диапазоне 80 — 9F (128 — 159).


C> Символ с кодом 0xEDA082 имеет двоичное представление 11101101 10100000 10000010, что соответствует кодировке UTF-8. Кроме того после ED следует код A0, который лежит в указанном вами диапазоне 80 — 9F.


A0 — это 160, а диапазон от 128 до 159 включительно. Кстати, U+D802 это вообще старший суррогат, и он сам по себе закодирован быть не может.

C> Правда я не понимаю почему байт после байта маркера должен иметь значения именно в диапазоне 80 — 9F, т.к. если учесть, что этот байт кодируется как 10xxxxxx, то он может принимать значения от 10000000 до 10111111, т.е. диапазон будет 80-BF.


Потому что так сказано в спецификации UTF-8. Там даются пояснения. Насколько я помню, это связано с однозначностью декодирования и в целях безопасности.

C> H>В-третьих нет ничего удивительно в том, что GetChars для одного юникод-кодпоинта вернет два символа т.к. supplementary-диапазон юникода ( > FFFF) представляется в UTF-16 (а виндовый юникод всегда представлен в UTF-16) в виде суррогатной пары.


C> Вот тут поподробнее я ни чего не понял


Так все просто. Юникод это BMP (basic multilingual plane, коды 0 — 0xFFFF) и Supplementary (коды 0x10000 — 0x10FFFF) диапазоны. В BMP еще входят два поддиапазона суррогатов (0xD800 — 0xDBFF — старшие суррогаты, 0xDC00 — 0xDFFF — младшие суррогаты). Суррогаты нужны для представления кодпоинтов из диапазона supplementary в кодировке UTF-16. Каждый кодпоинт из supplementary, в UTF-16, будет представлен суррогатной парой — старший суррогат + младший суррогат. Суррогаты сами по себе не являются значимыми юникод-кодпоинтами и их кодировать вообще нельзя, т.е. корректный кодировщик встретив одиночный суррогат должен заменить его замещающим кодпоинтом 0xFFFD; Кодировщик юникода, встретив суррогатную пару, сначала преобразует ее в кодпоинт и только потом этот кодпоинт кодирует.
avalon 1.0rc3 rev 380, zlib 1.2.3
Re[4]: Преобразование символов в UTF-8 ?
От: Cynic Россия  
Дата: 22.03.11 18:54
Оценка:
Здравствуйте, hattab, Вы писали:

H>Так все просто. Юникод это BMP (basic multilingual plane, коды 0 — 0xFFFF) и Supplementary (коды 0x10000 — 0x10FFFF) диапазоны. В BMP еще входят два поддиапазона суррогатов (0xD800 — 0xDBFF — старшие суррогаты, 0xDC00 — 0xDFFF — младшие суррогаты). Суррогаты нужны для представления кодпоинтов из диапазона supplementary в кодировке UTF-16. Каждый кодпоинт из supplementary, в UTF-16, будет представлен суррогатной парой — старший суррогат + младший суррогат. Суррогаты сами по себе не являются значимыми юникод-кодпоинтами и их кодировать вообще нельзя, т.е. корректный кодировщик встретив одиночный суррогат должен заменить его замещающим кодпоинтом 0xFFFD; Кодировщик юникода, встретив суррогатную пару, сначала преобразует ее в кодпоинт и только потом этот кодпоинт кодирует.


Про суррагатные пары и UTF-16 можно поподробнее? А то то что я читаю, как-то фигово написано не вс1 понял
:)
Re[5]: Преобразование символов в UTF-8 ?
От: hattab  
Дата: 22.03.11 19:53
Оценка: 62 (1) +1
Здравствуйте, Cynic, Вы писали:

C> H>Так все просто. Юникод это BMP (basic multilingual plane, коды 0 — 0xFFFF) и Supplementary (коды 0x10000 — 0x10FFFF) диапазоны. В BMP еще входят два поддиапазона суррогатов (0xD800 — 0xDBFF — старшие суррогаты, 0xDC00 — 0xDFFF — младшие суррогаты). Суррогаты нужны для представления кодпоинтов из диапазона supplementary в кодировке UTF-16. Каждый кодпоинт из supplementary, в UTF-16, будет представлен суррогатной парой — старший суррогат + младший суррогат. Суррогаты сами по себе не являются значимыми юникод-кодпоинтами и их кодировать вообще нельзя, т.е. корректный кодировщик встретив одиночный суррогат должен заменить его замещающим кодпоинтом 0xFFFD; Кодировщик юникода, встретив суррогатную пару, сначала преобразует ее в кодпоинт и только потом этот кодпоинт кодирует.


C> Про суррагатные пары и UTF-16 можно поподробнее? А то то что я читаю, как-то фигово написано не вс1 понял


В UTF-16 без преобразований можно представить только те кодпоинты, которые меньше 65536. Те, что больше должны быть представлены суррогатной парой. Суррогатная пара это два кодпоинта из соответствующих поддиапазонов (выше обозначены). Сначала идет старший суррогат затем младший. Но сами суррогаты при перекодировании, скажем в UTF-8, не кодируются, из них сперва собирается кодпоинт и кодируется уже он.

Пример: кодпоинт 0x20000. Представлен в UTF-16 так: 0xD840:0xDC00, а в UTF-8 так: 0xF0:0xA0:0x80:0x80.
avalon 1.0rc3 rev 380, zlib 1.2.3
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.