а utf8 это и есть unicode вопрос не очень корректный utf8 это один из способов реализации unicode imho а вот из дельфи system.pas Код (Text): function Utf8ToUnicode(Dest: PWideChar; MaxDestChars: Cardinal; Source: PChar; SourceBytes: Cardinal): Cardinal; var i, count: Cardinal; c: Byte; wc: Cardinal; begin if Source = nil then begin Result := 0; Exit; end; Result := Cardinal(-1); count := 0; i := 0; if Dest <> nil then begin while (i < SourceBytes) and (count < MaxDestChars) do begin wc := Cardinal(Source[i]); Inc(i); if (wc and $80) <> 0 then begin if i >= SourceBytes then Exit; // incomplete multibyte char wc := wc and $3F; if (wc and $20) <> 0 then begin c := Byte(Source[i]); Inc(i); if (c and $C0) <> $80 then Exit; // malformed trail byte or out of range char if i >= SourceBytes then Exit; // incomplete multibyte char wc := (wc shl 6) or (c and $3F); end; c := Byte(Source[i]); Inc(i); if (c and $C0) <> $80 then Exit; // malformed trail byte Dest[count] := WideChar((wc shl 6) or (c and $3F)); end else Dest[count] := WideChar(wc); Inc(count); end; if count >= MaxDestChars then count := MaxDestChars-1; Dest[count] := #0; end else begin while (i < SourceBytes) do begin c := Byte(Source[i]); Inc(i); if (c and $80) <> 0 then begin if i >= SourceBytes then Exit; // incomplete multibyte char c := c and $3F; if (c and $20) <> 0 then begin c := Byte(Source[i]); Inc(i); if (c and $C0) <> $80 then Exit; // malformed trail byte or out of range char if i >= SourceBytes then Exit; // incomplete multibyte char end; c := Byte(Source[i]); Inc(i); if (c and $C0) <> $80 then Exit; // malformed trail byte end; Inc(count); end; end; Result := count+1; end;
_DEN_ не надо stfw как говорит _S_T_A_S search the fucking web http://www.google.com/search?client=opera&rls=en&q=utf8toUnicode+c%2B%2B
Юникод к UTF имеет столь же отдалённое отношение, как ASCIIZ к safe-array. UTF16 очень напоминает юникод, но таковым не является, а UTF8 скорее похож на ASCII.
Quantum ты не прав насчёт unicode/utf8/utf16 и их отношения UTF-1 has only historical interest, having been removed from ISO/IEC 10646. UTF-7 has the quality of encoding the full BMP repertoire using only octets with the high-order bit clear (7 bit US-ASCII values, [US-ASCII]), and is thus deemed a mail-safe encoding ([RFC2152]). UTF-8, the object of this memo, uses all bits of an octet, but has the quality of preserving the full US-ASCII range: US-ASCII characters are encoded in one octet having the normal US- ASCII value, and any octet with such a value can only stand for an US-ASCII character, and nothing else. UTF-16 is a scheme for transforming a subset of the UCS-4 repertoire into pairs of UCS-2 values from a reserved range. UTF-16 impacts UTF-8 in that UCS-2 values from the reserved range must be treated specially in the UTF-8 transformation. iso ucs и unicode сейчас практически одно и тоже хотя формальные различия имеются - unicode более строгий стандарт
staier Я не нашёл в вышеприведенной цитате опровержения своих слов. И где здесь UTF? Обоснуйте, пожалуйста.
utf-8 это iso ucs utf-16 это iso ucs & unicode utf-8 входит в utf-16 как подмножество Asterix это я "опопсел" а не wasm впрочем продолжив ваш флейм замечу, что если иметь в виду популярность языка среди широких масс индусских программистов то соотношение явно в пользу с++
staier UCS (если я правильно понял спецификацию, но речь изначально всё равно шла не о UCS) и Unicode - это схемы кодирования символов, а UTF - это формат хранения текстовых строк. Что же мы яблоки с экскаваторами сравниваем?
Quantum что такое схема кодирования и чем она отличается от формата хранения в данном случае? проще говоря utf это один из механизмов в совокупности составляющих ucs соответтственно utf это элемент множества ucs а unicode это подмножество ucs utf это один из способов реализации transformation within ucs/unicode specification ладно , я вижу у нас идёт какой - то абстрактный спор о терминологии в котором я лично не вижу никакого практического смысла
staier Допустим, что нам необходимо представить один или более китайских иероглифов. Решение: применяем схему кодирования (ucs или юникод). Юникод, кстати, более ограничен, чем ucs, но для simplified chinese сойдёт. А теперь представьте, что нам необходимо сохранить текстовую последовательность (строку, например). Решение: конвертируем то, что мы получили при помощи схемы кодирования, в формат хранения типа UTF. UTF имеет заголовок, содержащий количество символов в текстовой строке, чем отдалённо напоминает паскалевые строки. Также могу добавить, что UTF выбирает схему кодирования (ascii, юникод, ucs) с оптимальным размером символа под конкретную строку, т.е. "обычные" ASCII-символы в UTF занимают 1 байт, а китайские иероглифы - по 2-4 байта. Практического смысла действительно мало.
хм.. почитал я тут всего, со многим и не согласен. Unicode - это в общем система символов, содержащая любые азбуки, и служебные символы, а вот кодировка - это способ представления юникода. В вин32 (и не только =) принято юникодом считать символ в слово (2 байта), что не очень удобно для разных систем пересылки данных, интернета и т.д., где обычно концом сообщения является двоичный нуль. Сами представте, сколько у нас символов (в 2 байта) содержащих двоичный нуль (либо в младшем, либо в старшем байте). Конец такой юникодовской строки является тоже нуль, только в одно слово (два байта по нулю). Ввиду такой проблемы и были введены кодировки (они не содержат однобайтового нуля - он кодирует конец строки). Вообще, честно говоря, все винды на платформе NT для отображения текста на окнах работают только с юникодом (с тем, который двух-байтовый, а не кодировки), такие символы еще называют WideChar (широкий, или двух-байтовый, в отличие от ANSI - однобайтовой). Кто просматривал секцию ресурсов, должно быть замечал, что там тоже все только в юникоде. Поэтому, каждый раз, как вы вызываете ANSI версию API (для однобайтовых символов), например MessageBoxA, система тратит лишнее время на перекодирование этого сообщения в Unicode (2 byte), и только потом вызывает WideChar версию API (MessageBoxW). Подробно об этом можно прочитать в книге Джеффри Рихтера. Теперь что касается UTF-8, и в общем говоря, тот самый вопрос, что меня сюда привел. UTF-8 кодируется следующим образом: в этой кодировке один символ юникода занимает от 1 до 6 байт. если символ находиться в диапазоне от 0 до 80h (т.е. старший бит ведущего байта сброшен) - он 100% занимает 1 байт. Остальные символы кодируются по следующему алгоритму: первый байт назовем ведущим (выделен жирным). 1 : 0xxxxxxx 2 : 110xxxxx 10xxxxxx 3 : 1110xxxx 10xxxxxx 10xxxxxx 4 : 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx 5 : 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 6 : 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx Как видно, что ведущий байт не может начинаться с 10 или с 1111111, да и вообще, все, что не подходит под этот алгоритм, нарушает кодировку UTF-8. К примеру: откроем обычный блокнот (notepad), и попробуем туда записать ОЁ (2 большие русские буквы о и ё). Сохраним файлик, и заного откроем его блокнотом... да, уже видем не наши ОЁ, а греческую букву ПСИ. Все потому, что блокнот каждый раз при открытии файла проверяет его на верность кодировки UTF-8 по выше приведенному алгоритму. Если все верно, он отображает нам уже переведенную последовательно символов в юникод (вызвав функцию MultiByteToWideChar с кодовой страницей CP_UTF8 (65001)). В действительности что такое ОЁ : CE A8 = 11001110 10101000 Теперь самое интересное : ввиду такого большого диапазона значений (кому не лень, можете пересчитать, сколько всего возможных символов можно получить в UTF-8) не все символы являются переводимыми в юникод (его диапазон всего лишь 65535 символов). Проделаем тоже самое с блокнотом, только теперь за место ОЁ запишем 4 байта : фёёё !!! вот так вот, переоткрыв файл мы ничего не увидим, но размер файла попрежнему 4 байта. Все верно, просто фёёё тоже подходит под алгоритм кодирования UTF-8, но он не имеет эквивалентного символа в юникоде. фёёё: F4 B8 B8 B8 = 11110100 10111000 10111000 10111000 Эту проблему можно легко избежать, т.к. MultiByteToWideChar поддерживает такую проверку. Для такой проверки достаточно вызвать MultiByteToWideChar с флагом MB_ERR_INVALID_CHARS (8). Если кодировка не имеет перевода в юникод, то GetLastError вернет ERROR_NO_UNICODE_TRANSLATION Код (Text): lea edi,[Buffer] lea esi,[szText1] Invoke MultiByteToWideChar,65001,8,esi,-1,edi,0 Invoke GetLastError xor edx,edx inc edx xor eax,ERROR_NO_UNICODE_TRANSLATION cmovnz eax,edx 65001 - Code page UTF-8 8 - MB_ERR_INVALID_CHARS -1 - размер исходного буфера, или буфера, содержащего Мультибайтовую строку (это не юникод, а кодировка (заканчивается двоичным нулем в один байт)), указав -1 (или 0FFFFFFFFh - максимальный размер), мы указываем на то, что API сама высчитает конец строки по однобайтовому нулю. 0 - размер конечного буфера, если мы не уверены, что у нас кодировка верна, мы ничего не переводим, а лишь только проверяем на правильность кодировки, но если указать размер, отличный от нуля, мы получим не только результат проверки, но и перекодированную мультибайтовую строку в юникод. Казалось бы, какие еще могут быть проблемы... Но с одной такой проблемой я и столкнулся. В выше приведенном примере если szText1 будет содержать "ф",0 - что никаким образом не соответствует кодировке UTF-8, мы получим ложный результат =\, GetLastError не вернет нам ERROR_NO_UNICODE_TRANSLATION. Эту проблему можно решить двумя способами : 1) в размере Мультибайтового буфера указать длину нашей строки (для "ф",0 это 1) 2) еще раз самим убедиться на правильность кодировки. в случае 1) нам придется вычислять дополнительно длину строки (до однобайтового двоичного нуля). в случае 2) нам придется проверять весь алгоритм самим. Конечно проще не заморачиваться на все эти биты, а просто идти по пути 1), но кто знает, может такой конфликт произойти и с указанием длины строки... На этот пример с "ф" я наткнулся случайно (кстати не только с "ф" такое, еще есть несколько символов). Может кому повезет больше, и такое не соответствие произойдет и с указанием длины буфера. На всякий случай приведу пример кода, для тех, кто пойдет по пути 2) =) Код (Text): IsUTF8String proc stdcall Src:DWORD nop org $-4 pushad mov esi,[esp+4+20h] IsUTF8_MainLoop: xor ebx,ebx lodsb test al,al jz Short IsUTF8_ret test al,80h jz Short IsUTF8_MainLoop or ecx,-1 ;ecx=-1 shl al,1 @@: inc ecx shl al,1 jc Short @B or ebx,-1 jecxz Short IsUTF8_ret @@: lodsb and al,11000000b xor al,80h jnz Short IsUTF8_ret dec ecx jnz Short @B mov esi,esi jmp Short IsUTF8_MainLoop IsUTF8_ret: inc ebx mov [esp+1Ch],ebx ;eax in stack popad retn 4 IsUTF8String endp есть более оптимизированный вариант (по времени выполнения) Код (Text): IsUTF8String proc stdcall Src:DWORD nop org $-4 pushad mov esi,[esp+4+20h] IsUTF8_MainLoop: xor ebx,ebx lodsb test al,al jz Short IsUTF8_ret shl al,1 jnc Short IsUTF8_MainLoop ;al=1 xxxxxxx or ebx,-1 shl al,1 jnc Short IsUTF8_ret ;al=1 0 ...... not utf8 shl al,1 jnc Short IsUTF8_2b ;al=11 0 xxxxx shl al,1 jnc Short IsUTF8_3b ;al=111 0 xxxx shl al,1 jnc Short IsUTF8_4b ;al=1111 0 xxx shl al,1 jnc Short IsUTF8_5b ;al=11111 0 xx shl al,1 jc Short IsUTF8_ret ;al=111111 0 x IsUTF8_6b: mov eax,[esi] add esi,4 and eax,0C0C0C0C0h xor eax,080808080h jnz Short IsUTF8_ret IsUTF8_2b: mov al,[esi] and al,0C0h xor al,080h jnz Short IsUTF8_ret inc esi jmp Short IsUTF8_MainLoop IsUTF8_3b: mov eax,[esi] and eax,0C0C0h xor eax,08080h jnz Short IsUTF8_ret inc esi inc esi jmp Short IsUTF8_MainLoop IsUTF8_4b: mov eax,[esi] and eax,0C0C0C0h xor eax,0808080h jnz Short IsUTF8_ret add esi,3 jmp Short IsUTF8_MainLoop IsUTF8_5b: mov eax,[esi] add esi,4 and eax,0C0C0C0C0h xor eax,080808080h jz Short IsUTF8_MainLoop IsUTF8_ret: inc ebx mov [esp+1Ch],ebx ;eax in stack popad retn 4 IsUTF8String endp
Кодировки вроде бы были введены задолго до создания юникода Отнюдь не всё, только строки. В остальном довольно познавательно.
Ну на самом деле по поводу ввода, вернее причин ввода, кодировок чисто ИМХО, или я бы даже сказал предположение. Хотя набрался смелости выложить =). Так или иначе спасибо, что поправил =). А вот с оптимизированным вариантом я лажанулся =), но уже подправил, ведь специально расположил проверку на 2-х байтовый вариант (тест 1 байта) сразу за проверкой на 6-байтовый вариант, но зачем-то продублировал один и тот же код =). Да и джампы теперь все короткие =).
Всем-всем-всем: чтобы больше не лажаться, открываем http://ru.wikipedia.org/wiki/Юникод и внимательно читаем статью от начала до конца.