Які відмінності між UTF-8, UTF-16 та UTF-32?
Я розумію, що всі вони зберігатимуть Unicode, і що кожен використовує різну кількість байтів для представлення символу. Чи є перевага у виборі одного над іншим?
Які відмінності між UTF-8, UTF-16 та UTF-32?
Я розумію, що всі вони зберігатимуть Unicode, і що кожен використовує різну кількість байтів для представлення символу. Чи є перевага у виборі одного над іншим?
Відповіді:
UTF-8 має перевагу в тому випадку, коли символи ASCII представляють більшість символів у текстовому блоці, оскільки UTF-8 кодує їх у 8 біт (як ASCII). Також вигідно, що файл UTF-8, що містить лише символи ASCII, має таке ж кодування, як і файл ASCII.
UTF-16 кращий там, де ASCII не переважає, оскільки в основному він використовує 2 байти на символ. UTF-8 почне використовувати 3 або більше байт для символів вищого порядку, де UTF-16 залишається лише 2 байти для більшості символів.
UTF-32 покриє всі можливі символи в 4 байти. Це робить його досить роздутим. Я не можу придумати жодної переваги його використання.
Коротко:
wchar_t
налаштуваннях за замовчуванням OSX та Linux на 4 байти. gcc має опцію, -fshort-wchar
яка зменшує розмір до 2 байтів, але порушує бінарну сумісність зі std libs.
UTF-8 є змінною від 1 до 4 байтів.
UTF-16 є змінною 2 або 4 байти.
UTF-32 фіксується 4 байтами.
Примітка: UTF-8 може приймати від 1 до 6 байтів за останнім звичаєм: https://lists.gnu.org/archive/html/help-flex/2005-01/msg00030.html
Unicode визначає єдиний величезний набір символів, присвоюючи кожному унікальному цілому значенню для кожного графічного символу (що є основним спрощенням і насправді не відповідає дійсності, але це досить близько для цілей цього питання). UTF-8/16/32 - це просто різні способи кодування цього.
Якщо коротко, UTF-32 використовує 32-бітні значення для кожного символу. Це дозволяє їм використовувати код фіксованої ширини для кожного символу.
UTF-16 використовує 16-бітний за замовчуванням, але це дає лише 65 кб можливих символів, що ніде недостатньо для повного набору Unicode. Так деякі символи використовують пари 16-бітних значень.
І UTF-8 використовує 8-бітні значення за замовчуванням, це означає, що 127 перших значень є однобайтовими символами фіксованої ширини (найзначніший біт використовується для означення того, що це початок багатобайтової послідовності, залишаючи 7 біти для фактичного значення символу). Усі інші символи кодуються як послідовності до 4-х байт (якщо служить пам'ять).
І це призводить нас до переваг. Будь-який символ ASCII безпосередньо сумісний з UTF-8, тому для оновлення застарілих програм UTF-8 - це звичайний і очевидний вибір. Майже у всіх випадках він також використовуватиме найменше пам'яті. З іншого боку, ви не можете гарантувати ширину символу. Це може бути 1, 2, 3 або 4 символи в ширину, що ускладнює маніпуляції з рядками.
UTF-32 є навпаки, він використовує найбільшу пам’ять (кожен символ має фіксовану ширину в 4 байти), але з іншого боку, ви знаєте, що кожен символ має таку точну довжину, тому маніпуляція з рядками стає набагато простішою. Ви можете обчислити кількість символів у рядку просто з довжини в байтах рядка. З UTF-8 цього не можна зробити.
UTF-16 - це компроміс. Це дозволяє більшості символів вписуватися у 16-бітове значення фіксованої ширини. Тож поки у вас немає китайських символів, музичних нот чи деяких інших, ви можете припустити, що кожен символ шириною 16 біт. Він використовує менше пам'яті, ніж UTF-32. Але це в чомусь "найгірше з обох світів". Він майже завжди використовує більше пам’яті, ніж UTF-8, і все ще не уникає проблеми, яка стикається з UTF-8 (символи змінної довжини).
Нарешті, часто корисно просто поговорити з тим, що підтримує платформа. Windows використовує UTF-16 внутрішньо, тому для Windows це очевидний вибір.
Linux дещо відрізняється, але вони, як правило, використовують UTF-8 для всього, що відповідає сумісності Unicode.
Отже, коротка відповідь: Усі три кодування можуть кодувати один і той же набір символів, але вони представляють кожен символ як різні послідовності байтів.
Unicode - це стандарт, і про UTF-x ви можете розглядати як технічну реалізацію для деяких практичних цілей:
Я спробував дати просте пояснення у своєму пості .
для кодування будь-якого символу потрібно 32 біта (4 байти) . Наприклад, щоб представити кодову точку символу "А" за допомогою цієї схеми, вам потрібно буде записати 65 у 32-бітному двійковому номері:
00000000 00000000 00000000 01000001 (Big Endian)
Якщо ви придивитесь уважніше, то зауважте, що найбільш правильні сім біт - це фактично ті самі біти при використанні схеми ASCII. Але оскільки UTF-32 є схемою фіксованої ширини , ми повинні приєднати три додаткові байти. Це означає, що якщо у нас є два файли, що містять лише символ "А", один - кодований ASCII, а другий - кодований UTF-32, їх розмір буде відповідно 1 байт і 4 байти.
Багато людей думають, що оскільки UTF-32 використовує 32-біт фіксованої ширини для представлення кодової точки, UTF-16 має фіксовану ширину 16 біт. НЕ ПРАВО!
У UTF-16 кодова точка може бути представлена або в 16 бітах, або в 32 бітах. Отже ця схема є системою кодування змінної довжини. Яка перевага перед UTF-32? Принаймні для ASCII, розмір файлів не буде в 4 рази більше від оригіналу (але все одно вдвічі), тому ми все ще не сумісні з ASCII.
Оскільки 7-бітів вистачає для представлення символу "А", тепер ми можемо використовувати 2 байти замість 4, як UTF-32. Це буде виглядати так:
00000000 01000001
Ви правильно здогадалися. У UTF-8 точка коду, можливо, представлена з використанням 32, 16, 24 або 8 біт, а як система UTF-16, ця також є системою кодування змінної довжини.
Нарешті, ми можемо представити "A" так само, як ми представляємо його за допомогою системи кодування ASCII:
01001101
Розглянемо китайську букву "語" - її кодування UTF-8:
11101000 10101010 10011110
Хоча кодування UTF-16 коротше:
10001010 10011110
Щоб зрозуміти представництво та те, як його тлумачити, відвідайте оригінальний пост.
UTF-8 стане найбільш ефективним для простору, якщо більшість персонажів не є з простору символів CJK (китайська, японська та корейська).
UTF-32 найкраще для випадкового доступу зі зміщенням символів у байтовий масив.
0xxxxxxx
у двійковій формі . Усі двобайтові символи починаються з 110xxxxx
другого байта 10xxxxxx
. Тож скажімо, перший символ двобайтового символу втрачено. Як тільки ви побачите 10xxxxxx
без попереднього 110xxxxxx
, ви зможете точно визначити, що байт був загублений або пошкоджений, і відкинути цей символ (або повторно запитати його з сервера чи будь-чого іншого), і рухатися далі, поки знову не побачите дійсний перший байт .
Я зробив кілька тестів для порівняння продуктивності бази даних між UTF-8 та UTF-16 в MySQL.
У UTF-32 всі символи кодуються 32 бітами. Перевага полягає в тому, що ви можете легко обчислити довжину струни. Недоліком є те, що на кожен символ ASCII ви витрачаєте зайві три байти.
У символах UTF-8 є змінна довжина, символи ASCII кодуються в одному байті (вісім біт), більшість західних спеціальних символів кодуються або в два байти, або в три байти (наприклад, € - три байти), і більш екзотичні символи можуть займати до чотирьох байтів. Очевидним недоліком є те, що апріорі ви не можете обчислити довжину рядка. Але для кодування тексту латинського (англійського) алфавіту потрібно набагато менше байтів, порівняно з UTF-32.
UTF-16 також має різну довжину. Символи кодуються або в два байти, або в чотири байти. Я справді не бачу сенсу. Він має недолік у тому, що він має змінну довжину, але не має переваги в тому, щоб заощадити стільки місця, скільки UTF-8.
З цих трьох, явно UTF-8 є найбільш поширеним.
Залежно від середовища розробки, у вас може навіть не бути вибору того, яке кодування тип рядкових даних буде використовуватися внутрішньо.
Але для зберігання та обміну даними я завжди використовую UTF-8, якщо у вас є вибір. Якщо у вас є в основному дані ASCII, це дасть вам найменший обсяг даних для передачі, при цьому все ще зможете кодувати все. Оптимізація для найменшого вводу-виводу - це спосіб просунути сучасні машини.
Як уже згадувалося, різниця полягає насамперед у розмірі базових змінних, які в кожному випадку стають більшими, щоб можна було представити більше символів.
Однак шрифти, кодування та речі є злісно складними (без потреби), тому потрібна велика посилання, щоб заповнити детальніше:
http://www.cs.tut.fi/~jkorpela/chars.html#ascii
Не сподівайтеся, що ви все це зрозумієте, але якщо згодом ви не хочете мати проблем, варто навчитися стільки, скільки зможете, як можна раніше (або просто змусити когось іншого розібратися для вас).
Пол.
Коротше кажучи, єдиною причиною використання UTF-16 або UTF-32 є підтримка відповідно неанглійських та старовинних сценаріїв.
Мені було цікаво, чому хтось вирішив би кодувати не UTF-8, коли це, очевидно, більш ефективно для цілей веб / програмування.
Поширене помилкове уявлення - суфіксне число НЕ вказує на його здатність. Всі вони підтримують повний Unicode, лише те, що UTF-8 може обробляти ASCII одним байтом, тому БІЛЬШЕ ефективні / менш корумповані для процесора та через Інтернет.
Хороше читання: http://www.personal.psu.edu/ejp10/blogs/gotunicode/2007/10/which_utf_do_i_use.html та http://utf8everywhere.org