UTF-8, UTF-16 та UTF-32


486

Які відмінності між UTF-8, UTF-16 та UTF-32?

Я розумію, що всі вони зберігатимуть Unicode, і що кожен використовує різну кількість байтів для представлення символу. Чи є перевага у виборі одного над іншим?


36
Перегляньте це відео, якщо вас цікавить, як працює Unicode youtube.com/watch?v=MijmeoH9LT4

1
Відео зосереджується на UTF-8, і так, це добре пояснює, як працює кодування змінної довжини і здебільшого сумісне з комп'ютерами, які читають або записують лише ASCII з фіксованою довжиною. Хлопці Unicode були розумні при розробці кодування UTF-8.
хвилини

1
Я створив онлайн-інструмент для перетворення та порівняння.
Аміт Кумар Гупта

1
UTF-8 є фактичним стандартом у більшості сучасних програм для збережених файлів . Більш конкретно, це найбільш широко використовуване кодування для HTML та файлів конфігурації та перекладу (Minecraft, наприклад, не приймає жодного іншого кодування для всієї його текстової інформації). UTF-32 є швидким для внутрішнього уявлення пам'яті , і UTF-16 є свого роду застарілим , в даний час використовується тільки в Win32 з історичних причин ( UTF-16 була фіксованою довжини , коли Windows 95 була річ)
Kotauskas

@ Владислав Тончаров UTF-16 ніколи не був кодування фіксованої довжини. Ви плутаєте це з UCS-2.

Відповіді:


373

UTF-8 має перевагу в тому випадку, коли символи ASCII представляють більшість символів у текстовому блоці, оскільки UTF-8 кодує їх у 8 біт (як ASCII). Також вигідно, що файл UTF-8, що містить лише символи ASCII, має таке ж кодування, як і файл ASCII.

UTF-16 кращий там, де ASCII не переважає, оскільки в основному він використовує 2 байти на символ. UTF-8 почне використовувати 3 або більше байт для символів вищого порядку, де UTF-16 залишається лише 2 байти для більшості символів.

UTF-32 покриє всі можливі символи в 4 байти. Це робить його досить роздутим. Я не можу придумати жодної переваги його використання.


165
Перевага UTF-32: вам не потрібно розшифровувати збережені дані до 32-бітної точки коду Unicode, наприклад, для символу в обробці символів. Точка коду вже доступна прямо у вашому масиві / векторі / рядку.
richq

22
Так само простіше розібратися, якщо (небо допоможе вам) вам доведеться знову реалізувати колесо.
Пол Макміллан

24
Ну, UTF-8 має перевагу в мережевих передачах - не потрібно турбуватися про витривалість, оскільки ви переносите дані по одному байту (на відміну від 4).
Тім Час

30
@richq У UTF-32 не можна обробляти символи за символами, оскільки кодова точка не завжди відповідає символу.
хамстерген

4
Перевага UTF-32: маніпулювання струнами можливо швидше порівняно з еквівалентом utf-8
Уес

331

Коротко:

  • UTF-8: кодування змінної ширини, сумісна назад з ASCII. Символи ASCII (U + 0000 до U + 007F) беруть 1 байт, кодові точки U + 0080 до U + 07FF беруть 2 байти, кодові точки U + 0800 до U + FFFF беруть 3 байти, кодові точки U + 10000 до U + 10FFFF візьміть 4 байти. Добре для англійського тексту, не дуже добре для азіатського тексту.
  • UTF-16: Кодування змінної ширини. Кодові точки U + 0000 до U + FFFF беруть 2 байти, а кодові точки U + 10000 до U + 10FFFF беруть 4 байти. Погане для англійського тексту, добре для азіатського тексту.
  • UTF-32: Кодування з фіксованою шириною. Усі кодові точки займають чотири байти. Величезна свиня для пам’яті, але швидка в роботі. Рідко використовується.

Якщо коротко: див. Вікіпедія: UTF-8 , UTF-16 та UTF-32 .


65
@spurrymoses: Я чітко маю на увазі кількість місця, зайняте байтами даних. Для UTF-8 потрібно 3 байти на азіатський символ, тоді як UTF-16 вимагає лише 2 байти на азіатський символ. Це насправді не є основною проблемою, оскільки комп’ютери мають тонни пам'яті в ці дні порівняно із середньою кількістю тексту, що зберігається в пам'яті програми.
Адам Розенфілд

12
UTF-32 вже не рідко використовується ... у wchar_tналаштуваннях за замовчуванням OSX та Linux на 4 байти. gcc має опцію, -fshort-wcharяка зменшує розмір до 2 байтів, але порушує бінарну сумісність зі std libs.
лоза

9
@PandaWood ofcource UTF-8 може кодувати будь-який символ! Але ви порівняли вимогу пам'яті з такою для UTF-16? Ви, здається, не вистачаєте точки!
Устаман Сангат

16
Якби хтось сказав, що UTF-8 "не дуже хороший для азіатського тексту" в контексті всіх форматів кодування, включаючи ті, які не можуть кодувати Unicode, вони, звичайно, помиляються. Але це не контекст. Контекст вимог до пам'яті походить від того, що питання (і відповідь) порівнює UTF-8, UTF-16 та UTF-32, які всі будуть кодувати азіатський текст, але використовуватимуть різні обсяги пам'яті / пам’яті. Звідси випливає, що їх відносна доброта, природно, була б цілком у контексті потреб пам'яті. "Не так добре"! = "Не добре".
Пол Григорій

5
@McGafter: Ну, звичайно, є. Якщо ви хочете довіритися, вирушайте прямо до рота коня в консорціумі Unicode . Дивіться розділ 2.5 для опису кодувань UTF- *. Але для отримання простого, високого рівня розуміння кодувань, я вважаю, що статті у Вікіпедії є набагато доступнішим джерелом.
Адам Розенфілд

116
  • 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


35
UTF8 - це фактично від 1 до 6 байт.
Urkle

6
@Urkle є технічно правильним, оскільки відображення повного спектру UTF32 / LE / BE включає U-00200000 - U-7FFFFFFF, хоча Unicode v6.3 закінчується на U-0010FFFF включно. Ось приємна розбивка щодо того, як кодувати / скорочувати 5 та 6 байт utf8: list.gnu.org/archive/html/help-flex/2005-01/msg00030.html

4
резервне копіювання їх відповідними довідковими частинами та їх джерелами?
n611x007

20
@Urkle Ні, UTF-8 не може бути 5 або 6 байт. Точки коду Unicode обмежені 21 бітом, що обмежує UTF-8 на 4 байти. (Можна, звичайно, розширити принцип UTF-8 для кодування довільних великих цілих чисел, але це не було б Unicode.) Див. RFC 3629.
rdb,

11
Цитуючи Вікіпедію: У листопаді 2003 року UTF-8 був обмежений RFC 3629, щоб відповідати обмеженням кодування символів UTF-16: явно забороняючи кодові точки, що відповідають високим та низьким сурогатним символам, видалено понад 3% трибайтових послідовностей , і закінчуючи на U + 10FFFF, видалено більше 48% чотирьохбайтових послідовностей та всіх п'ятибайтних і шестибайтових послідовностей.
Адам Кальвет Боль

79

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.

Отже, коротка відповідь: Усі три кодування можуть кодувати один і той же набір символів, але вони представляють кожен символ як різні послідовності байтів.


12
Неточно сказати, що Unicode присвоює кожному графічному символу унікальне ціле число . Він призначає таке кожній кодовій точці, але деякі кодові точки є невидимими символами управління , а деякі графічні символи вимагають представлення кількох кодових точок .
tchrist

15
@tchrist: так, це неточно. Проблема полягає в тому, що для точного пояснення Unicode потрібно написати тисячі сторінок. Я сподівався отримати базову концепцію, щоб пояснити різницю між кодуванням
jalf

@jalf lol так, що в основному для пояснення Unicode вам доведеться написати специфікацію основної характеристики Unicode
Джастін Омс

@tchrist Більш конкретно, ви можете сконструювати китайські символи з наданих примітивів (але вони знаходяться в одній діаграмі, тому ви просто в кінцевому підсумку використовуєте нереальну кількість місця - або диска, або оперативної пам’яті - для кодування), а не використовувати вбудовані.
Kotauskas

44

Unicode - це стандарт, і про UTF-x ви можете розглядати як технічну реалізацію для деяких практичних цілей:

  • UTF-8 - " оптимізований розмір ": найкраще підходить для даних на основі латинських символів (або ASCII), він займає лише 1 байт на символ, але розмір відповідно збільшується різноманітністю символів (і в гіршому випадку може вирости до 6 байт на символ)
  • UTF-16 - " баланс ": він займає мінімум 2 байти на символ, що достатньо для існуючого набору основних мов з фіксованим розміром на ньому, щоб полегшити обробку символів (але розмір все ще мінливий і може зростати до 4 байт на символ )
  • UTF-32 - " продуктивність ": дозволяє використовувати прості алгоритми в результаті символів фіксованого розміру (4 байти), але з недоліком пам'яті

«Основні мови» не те, що мейнстрім у багатьох частинах світу ^^
tuxayo

2
UTF-16 насправді розмір оптимізований для символів, що не належать до ASCII. Адже насправді залежить, якими мовами він буде використовуватися.
tuxayo

@tuxayo повністю згоден, варто відзначити набори персонажів Ханзі та Канджі для азіатської частини світу.
грак

Повинно відповісти. Це занадто правильно, щоб бути тут похованим.
Міхал Штейн

28

Я спробував дати просте пояснення у своєму пості .

UTF-32

для кодування будь-якого символу потрібно 32 біта (4 байти) . Наприклад, щоб представити кодову точку символу "А" за допомогою цієї схеми, вам потрібно буде записати 65 у 32-бітному двійковому номері:

00000000 00000000 00000000 01000001 (Big Endian)

Якщо ви придивитесь уважніше, то зауважте, що найбільш правильні сім біт - це фактично ті самі біти при використанні схеми ASCII. Але оскільки UTF-32 є схемою фіксованої ширини , ми повинні приєднати три додаткові байти. Це означає, що якщо у нас є два файли, що містять лише символ "А", один - кодований ASCII, а другий - кодований UTF-32, їх розмір буде відповідно 1 байт і 4 байти.

UTF-16

Багато людей думають, що оскільки UTF-32 використовує 32-біт фіксованої ширини для представлення кодової точки, UTF-16 має фіксовану ширину 16 біт. НЕ ПРАВО!

У UTF-16 кодова точка може бути представлена ​​або в 16 бітах, або в 32 бітах. Отже ця схема є системою кодування змінної довжини. Яка перевага перед UTF-32? Принаймні для ASCII, розмір файлів не буде в 4 рази більше від оригіналу (але все одно вдвічі), тому ми все ще не сумісні з ASCII.

Оскільки 7-бітів вистачає для представлення символу "А", тепер ми можемо використовувати 2 байти замість 4, як UTF-32. Це буде виглядати так:

00000000 01000001

UTF-8

Ви правильно здогадалися. У UTF-8 точка коду, можливо, представлена ​​з використанням 32, 16, 24 або 8 біт, а як система UTF-16, ця також є системою кодування змінної довжини.

Нарешті, ми можемо представити "A" так само, як ми представляємо його за допомогою системи кодування ASCII:

01001101

Невеликий приклад, коли UTF-16 насправді кращий, ніж UTF-8:

Розглянемо китайську букву "語" - її кодування UTF-8:

11101000 10101010 10011110

Хоча кодування UTF-16 коротше:

10001010 10011110

Щоб зрозуміти представництво та те, як його тлумачити, відвідайте оригінальний пост.


19

UTF-8

  • не має поняття байт-порядку
  • використовує від 1 до 4 байт на символ
  • ASCII - сумісний підмножина кодування
  • повністю само синхронізуючись, наприклад, скинутий байт з будь-якої точки потоку зіпсує максимум один символ
  • майже всі європейські мови закодовані в два байти або менше на символ

UTF-16

  • повинні бути проаналізовані відомим порядком байтів або читанням байтового порядку (BOM)
  • використовує 2 або 4 байти на символ

UTF-32

  • кожен символ - 4 байти
  • повинні бути проаналізовані відомим порядком байтів або читанням байтового порядку (BOM)

UTF-8 стане найбільш ефективним для простору, якщо більшість персонажів не є з простору символів CJK (китайська, японська та корейська).

UTF-32 найкраще для випадкового доступу зі зміщенням символів у байтовий масив.


Як працює "само синхронізація" в UTF-8? Чи можете ви навести приклади для 1 байта та 2 байтових символів?
Корай Тугай

2
@KorayTugay Дійсні короткі байтові рядки ніколи не використовуються у довших символах. Наприклад, ASCII знаходиться в діапазоні 0-127, тобто всі однобайтові символи мають вигляд 0xxxxxxxу двійковій формі . Усі двобайтові символи починаються з 110xxxxxдругого байта 10xxxxxx. Тож скажімо, перший символ двобайтового символу втрачено. Як тільки ви побачите 10xxxxxxбез попереднього 110xxxxxx, ви зможете точно визначити, що байт був загублений або пошкоджений, і відкинути цей символ (або повторно запитати його з сервера чи будь-чого іншого), і рухатися далі, поки знову не побачите дійсний перший байт .
Кріс

1
якщо у вас є зсув до символу, у вас є зміщення до цього символу - utf8, utf16 або utf32 буде працювати так само в цьому випадку; тобто всі вони однаково хороші у випадковому доступі за змістом символів у масив байтів. Думка, що utf32 краще підраховувати символи, ніж utf8, також є абсолютно помилковою. Елемент коду (який НЕ те ж саме, що знову - таки характер, це не те ж саме , як графеми .. зітхаю), становить 32 біта в UTF32 і від 8 до 32 бітів в utf8, але персонаж може охоплювати кілька кодових, які знищує головну перевагу, яку люди стверджують, що utf32 має над utf8.
Чітка

14

Я зробив кілька тестів для порівняння продуктивності бази даних між UTF-8 та UTF-16 в MySQL.

Оновити швидкості

UTF-8

Введіть тут опис зображення

UTF-16

Введіть тут опис зображення

Вставте швидкість

Введіть тут опис зображення

Введіть тут опис зображення

Видалити швидкості

Введіть тут опис зображення

Введіть тут опис зображення


14

У UTF-32 всі символи кодуються 32 бітами. Перевага полягає в тому, що ви можете легко обчислити довжину струни. Недоліком є ​​те, що на кожен символ ASCII ви витрачаєте зайві три байти.

У символах UTF-8 є змінна довжина, символи ASCII кодуються в одному байті (вісім біт), більшість західних спеціальних символів кодуються або в два байти, або в три байти (наприклад, € - три байти), і більш екзотичні символи можуть займати до чотирьох байтів. Очевидним недоліком є ​​те, що апріорі ви не можете обчислити довжину рядка. Але для кодування тексту латинського (англійського) алфавіту потрібно набагато менше байтів, порівняно з UTF-32.

UTF-16 також має різну довжину. Символи кодуються або в два байти, або в чотири байти. Я справді не бачу сенсу. Він має недолік у тому, що він має змінну довжину, але не має переваги в тому, щоб заощадити стільки місця, скільки UTF-8.

З цих трьох, явно UTF-8 є найбільш поширеним.


Чому я б хотів обчислити довжину рядка під час розробки веб-сайтів? Чи є якась перевага вибору UTF-8 / UTF-16 у веб-розробці?
Морфідон

"Перевага полягає в тому, що ви можете легко обчислити довжину рядка" Якщо ви визначите довжину на # кодових точок, то так, ви можете просто розділити довжину байта на 4, щоб отримати її за допомогою UTF-32. Однак це не дуже корисне визначення: воно може не стосуватися кількості символів. Також нормалізація може змінити кількість кодових точок у рядку. Наприклад, французьке слово "été" можна кодувати як мінімум 4 різними способами з 3 різними довжинами кодових точок.

UTF-16, можливо, швидше, ніж UTF-8, але також не витрачає пам'ять, як UTF-32.
Міхал Штейн

6

Залежно від середовища розробки, у вас може навіть не бути вибору того, яке кодування тип рядкових даних буде використовуватися внутрішньо.

Але для зберігання та обміну даними я завжди використовую UTF-8, якщо у вас є вибір. Якщо у вас є в основному дані ASCII, це дасть вам найменший обсяг даних для передачі, при цьому все ще зможете кодувати все. Оптимізація для найменшого вводу-виводу - це спосіб просунути сучасні машини.


Можливо, набагато важливішим, ніж космічні вимоги, є той факт, що UTF-8 не застрахований від витривалості. UTF-16 і UTF-32 неминуче повинні мати справу з проблемами витривалості, де UTF-8 - це просто потік октетів.
IIнеочікуваний

2

Як уже згадувалося, різниця полягає насамперед у розмірі базових змінних, які в кожному випадку стають більшими, щоб можна було представити більше символів.

Однак шрифти, кодування та речі є злісно складними (без потреби), тому потрібна велика посилання, щоб заповнити детальніше:

http://www.cs.tut.fi/~jkorpela/chars.html#ascii

Не сподівайтеся, що ви все це зрозумієте, але якщо згодом ви не хочете мати проблем, варто навчитися стільки, скільки зможете, як можна раніше (або просто змусити когось іншого розібратися для вас).

Пол.


або просто використовуйте UTF-8 за замовчуванням, оскільки він став стандартним фактичним фактором, і з’ясуйте, підтримує його нова система чи ні. якщо цього не відбувається, ви можете повернутися до цієї публікації.
robotik

-2

Коротше кажучи, єдиною причиною використання 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


Я не впевнений, чому ви припускаєте, що використання UTF-16 або UTF-32 було підтримкою не англійського тексту. UTF-8 може впоратися з цим просто чудово. І в англійському тексті є символи, які не є ASCII. Наче нульова ширина без столяра. Або ем тире. Боюся, ця відповідь не надає великої цінності.
ІІНеочікувана

Це питання може бути спровоковано, оскільки UTF-8 все ще часто використовується у файлах HTML, навіть якщо більшість символів є 3-байтовими символами UTF-8,
Ṃųỻịgǻňạcểơửṩ

@IInspectable підтримка - не найкраща редакція, просування або краща підтримка були б точнішими
robotik

Надсилання сторінки на зразок utf8everywhere.org - це не те, що я б робив у відповіді "SO".
Міхал Штейн
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.