Pull to refresh

Comments 51

Одно число называется битом, каждый бит состоит из восьми байтов.

что-то здесь не так…

В статье не хватает этой фразы


Unicode это набор символов, UTF — это кодировка

Да! Это и есть то, о чем должен знать каждый разработчик.


Если у вас Unicode-строка, то значит у вас нет байтов. Вы не можете Unicode передать по сети, записать на диск, посчитать хэш, перевести в base64. Для этого строку нужно закодировать используя одну из кодировок. Формально вы даже в памяти не можете хранить такую строку, её все равно нужно как-то кодировать, просто в некоторых языках это происходит прозрачно.


Если у вас UTF-строка, то значит у вас сырые баты. Вы не можете посчитать количество слов или символов, искать подстроку или разделять на части, не зная кодировку этой конкретной строки.

"не зная кодировку этой конкретной строки. " - А разве для UTF есть ещё какие-то наборы символов помимо Unicode?

Как следует из названия, кодовый пункт состоит из 8 битов (один байт). В Unicode есть символы, которые занимают несколько байтов (вплоть до 6). Это называют переменной длиной. В разных языках удельное количество байтов разное.
Если нужно, чтобы символ занимал больше одного байта, то применяется битовая комбинация, обозначающая переход — он говорит о том, что символ продолжается в нескольких следующих байтах.

Не очень понятно как это реализовано, что за битовая комбинация, можно пример?
Спасибо за статью. Меня всегда интересовало, почему на некоторых ресурсах которые представляют юникод символы или же эмодзи (например этот) не все символы показывает (просто пустой прямоугольник), хотя в теории они же должны быть, это от настроек операционной системы зависит, или как? С обновление винды, должны появляться новые символы?

Это обычно зависит от самого шрифта. Если он базируется на Arial, то в некоторых его сборках нету половины юникода.
Поэтому если в шрифте просто нету символа, то там прямоугольник

Это зависит много от чего, включая то, на что вы повлиять не можете. Например, на кодировку используемой сайтом базы данных.

А есть еще просто пустые места, в которых просто нет символов. Юникод еще не заполнен на 100%.
Здесь нельзя не написать про то, как BOM-символы постоянно ломают сайты тем, кто правит файлы в виндовых редакторах. Из-за того, что оказываются перед хедерами.

...и вот лично мне не совсем понятно, что с этим делать, кроме как использовать notepad++. Хотя должно же быть какое-то системное решение.

Системным решением стала бы поддержка BOM-символов со стороны PHP. В конце концов, BOM является частью RFC 3629, а не просто придурью виндового Блокнота.

В Unicode есть символы, которые занимают несколько байтов (вплоть до 6)


UTF-8 кодирует с помощью одного байта каждый кодовый пункт Unicode с 0 по 127 (как в ASCII).


идея не раскрыта
кодовых пунктов (кодовых точек)

Я действительно понимаю всю сложность, с которой столкнулся переводчик, но лучше было оставить английский вариант code point чем так переводить.

Интересно бывают ли в природе шрифты, в которых есть начертания всех 143 859 кодовых пунктов? (Кстати, эта важная часть в статье никак не раскрывается) Также интересно, сколько может весить такой файлик…
Что значит “в природе” и что значит “бывают”? TrueType разрабытывался во времяна Unicode 2.0, потому в одном TrueType шрифте бывает максимум 65535 глифов. Но OpenType позволет собрать в одну коллекцию несколько TrueType шрифтов.
И вообще: работа со шрифтами — это сильно отдельная вещь, даже небольшая часть описания этого всего — даёт статью заметно большую обсуждаемой.
А ведь потом из всего этого ещё и строку нужно сложить.

Всё это, к сожалению не прихоти разработчиков стандартов, а отражение того факта, что люди за тысячелетия придумали много, много, вот реально много всякого-разного для передачи текста на бумаге.
В UTF-8 используется один байт на пункт, в UTF-16 — два байта, в UTF-32 — четыре байта.

В UTF-8 используется от одного до четырёх байт на пункт, в UTF-16 — два или четыре байта, в UTF-32 — четыре байта.


В Unicode есть символы, которые занимают несколько байтов (вплоть до 6).

Не в Unicode, а в UTF-8. И не до 6, а до 4.


Статья очень низкого уровня, прочтение может только больше запутать.

Не в Unicode, а в UTF-8. И не до 6, а до 4.

Это в мирное время. А вот прилетят инопланетяне со своим юникодом, как Земля будет договариваться об условиях своей капитуляции? То-то же.
Символ (единица перемещения курсора / выделения) может состоять из нескольких пунктов; хотя ограничение в 6 байтов — действительно непонятно откуда взялось.

хотя ограничение в 6 байтов — действительно непонятно откуда взялось

Ограничения формата кодирования. В UTF-8 по первому байту определяется количество следующих за них хвостовых байтов.


0xxxxxxx — значения 0x0000..0x007F
110xxxxx + 1 × 10xxxxxx — значения 0x0080..0x07FF
1110xxxx + 2 × 10xxxxxx — значения 0x0800..0xFFFF
11110xxx + 3 × 10xxxxxx — значения 0x10000..0x10FFFF


а дальше Юникод заканчивается и больше вариантов не нужно. (И если присмотреться, то не все биты используются для кодирования).


Хотя если продолжить приницип кодирования, то можно получить комбинации:


111110xx + 4 × 10xxxxxx
1111110x + 5 × 10xxxxxx


А дальше уже место в первом байте заканчивается — на комбинации из шести байтов (1 начальных, 5 хвостовых).


Правда, часто забывают, что остаётся ещё 11111110, к которому можно приклеить что вам хочется; например, шесть хвостовых байтов, чтобы получить комбинацию из семи «типа UTF-8».

Хотя если продолжить приницип кодирования, то можно получить комбинации

Это очевидно, но это не UTF-8, а разговор про UTF-8.

Я думаю это была проблема того, что переводчик не понял что означает пункт и что означает длина всего символа.

Не в Unicode, а в UTF-8. И не до 6, а до 4.

До четырех урезали в 2003, до этого было до 6.

В оригинале то же самое:


Unicode is made up of lots of code points (mapping lots of characters from around the world to a key that all computers can reference.) A collection of code points is called a character set — which is what Unicode is.

But there are different types of UTF standards. They differ depending on the amount of bytes used to encode one code point. It also depends on whether you're using UTF-8 (one byte per code point), UTF-16 (two bytes per code point) or UTF-32 (four bytes per code point).
Попробуйте сами, как выглядит бнопня. Это поможет понять, насколько важна кодировка.


Те, кто знает не понаслышке, что такое бНОПНЯ вводят адрес транслитом, а имена файлов — без пробелов)

UFO just landed and posted this here

Почему бы не раскрыть, откуда пошла бНОПНЯ, и кто такие KOI8-R и CP-1251?

Префикс U+ говорит о том, что это стандарт Unicode, а число — это результат преобразования двоичных чисел. Стандарт использует шестнадцатеричную нотацию, которая является упрощённым представлением двоичных чисел.


Почему двоичных? Любых чисел. Да и вообще, что такое «двоичное число»? Есть двоичная система, есть двоичные цифры, а вот сами числа вообще к системам счисления не привязаны.

статья написана школьником, школьным стилем для школоты. пойдет только как доклад в школе. никакой информации не несёт, полно неточностей и ошибок, чего только стоит "Unicode Transform Protocol (UTF)"

Зато интересно, почему она вдруг выстрелила в топ. Написана она аж год назад.

Администрация хабра тестирует функцию вывода, на их мнение, хороших технических статей в топ и даже довольно старых, из-за их отсутствия сейчас.

Я вот с удовольствием прочитал, а остальное уточнил уже отдельно. Статья действительно написана простым языком, даже слишком простым, но информацию всё же несёт. Школьники тоже читают Хабр.

Есть конечно что добавить, те же самые биты 0xxxxx, 110xxxx, 10xxxx, а также про отсуствие BOM.

Сижу сдерживаюсь, чтобы не написать ответ комментам годовой давности.

Сижу сдерживаюсь, чтобы не написать ответ комментам годовой давности.

А зачем сдерживаться-то?

Переход на utf-8 - это очевидная неизбежность, но как же при этом просела скорость regex...

Да, или медленно, или никак. Это цена использования не-ASCII. Кроме регулярок, в том же Golang или JS есть сортировка строк по алфавиту, и вот она отличается для разных языков (немецкий и прочее), colator. Вот например, Javascript^

const words = ['Bären', 'Käfer', 'küssen', 'Ähnlich', 'Äpfel'];
words.sort(Intl.Collator().compare);

А теперь вспомним русский.

const words = ['Арбуз', 'Баран', 'Ель', 'Ёлка', 'Жизнь', 'Ähnlich', 'Äpfel'];
words.sort(Intl.Collator().compare);
// ['Арбуз', 'Баран', 'Ёлка', 'Ель', 'Жизнь', 'Ähnlich', 'Äpfel']

Буква Ё должна быть после Е, но в UTF/Unicode она стоит перед ней. Соотвественно, с точки зрения кода проще сравнивать буквы как числа, но это не правильно. Да и в разных браузерах результат в теории может отличаться. Но в любом случае это правильнее, чем ставить ё в самом начале или конце.

Если сортировть "в лоб", то результат другой:

const words = ['Арбуз', 'Баран',  'Ель', 'Ёлка', 'Жизнь', 'Ähnlich', 'Äpfel'];
words.sort();
// ['Ähnlich', 'Äpfel', 'Ёлка', 'Арбуз', 'Баран', 'Ель', 'Жизнь']

А теперь golang для примера. https://go.dev/play/p/DMWXWjPwTB5

Результат (для немецкого языка и русского языков одинаковый):

[Ähnlich Äpfel Арбуз Баран Ёлка Ель Жизнь]

Ähnlich прыгнуло в начало. Он должен быть рядом с буквой A, а Ё должен быть рядом с буквой Е.

То есть само наличие разных алфавитов усложняет такую банальную вещь, как сортировка, это не Unicode виноват и не UTF, просто человеческий багаж знаний, информации больше, чем количество байт в слове, означающем что-либо. И с этим надо жить.

У меня несколько отстранённый вопрос, тем не менее частично связанный с Unicode-ом.

Наверняка все видели т.н. zalgo-текст. Никто не знает, как его эффективно фильтровать? Видел пример подобной фильтрации например в Discord-е. Может кто-нибудь знает о какой-нибудь библиотеки для .NET?

Можно сделать связкой регулярка+encodeURI.

Для JS:

const re = /%CC%/g
const hasZalgo = txt => re.test(encodeURIComponent(txt));  
hasZalgo(string) //true или false

шумерскую клинопись (Хабр её не отображает)

Хабр прекрасно передаёт отдаёт и принимает клинопись, как и любой другой юникод.
𒃱. Далее - проблема шрифтов. Её может решить хабр для всех, или вы для себя. Хабру на клинопись плевать.

На самом деле некоторое время назад (видимо, в том числе на момент написания этого поста) Хабру было не плевать из-за того, что в MySQL-базе использовалась кодировка utf8mb3 (также известна как просто utf8), из-за которой тексты обрезались по первому четырёхбайтовому символу — в частности, Emoji и клинописи.

Судя по тому, что в 2022 году эта проблема уже не воспроизводится — видимо, её каким-то образом решили (сконвертировали базу в utf8mb4, воткнули экранирование четырёхбайтовых utf-8, вообще перешли на постгрес?)

(немного четырёхбайтовых Emoji для теста: 🎼 🙃 🌠)

Ага. Я теперь буду смотреть дату публикации статьи.

Ещё было годное развлечение в конец ника поставить юникод-символ ‮ который разворачивает последующие символы задом-наперёд.

Потом забавно отображаются переписка и системные сообщения.

UFO just landed and posted this here

Я застал дистрибутивы Linux до перехода на UTF-8, и это была боль. Русификация отнимала существенную часть душевных сил. Монтировать NTFS надо было с указанием кодировки, теги в MP3 по-русски никогда сразу не отображались, русские имена файлов на CD и флешках, в ZIP-архивах тоже.

Юникод - великая вещь!

UFO just landed and posted this here
Sign up to leave a comment.