UTF-8, UTF-16 ve UTF-32 arasındaki farklar nelerdir?
Hepsinin Unicode depolayacağını ve her birinin bir karakteri temsil etmek için farklı sayıda bayt kullandığını anlıyorum. Birini diğerinden seçmenin bir avantajı var mı?
UTF-8, UTF-16 ve UTF-32 arasındaki farklar nelerdir?
Hepsinin Unicode depolayacağını ve her birinin bir karakteri temsil etmek için farklı sayıda bayt kullandığını anlıyorum. Birini diğerinden seçmenin bir avantajı var mı?
Yanıtlar:
UTF-8, ASCII karakterlerinin bir metin bloğundaki karakterlerin çoğunu temsil etmesi durumunda bir avantaja sahiptir, çünkü UTF-8 bunları 8 bit (ASCII gibi) olarak kodlar. Yalnızca ASCII karakterleri içeren bir UTF-8 dosyasının bir ASCII dosyasıyla aynı kodlamaya sahip olması da avantajlıdır.
UTF-16, ASCII'nin baskın olmadığı yerlerde daha iyidir, çünkü öncelikle karakter başına 2 bayt kullanır. UTF-8, üst düzey karakterler için 3 veya daha fazla bayt kullanmaya başlar; burada UTF-16, çoğu karakter için sadece 2 bayta kalır.
UTF-32, 4 bayt içindeki tüm olası karakterleri kapsayacaktır. Bu onu oldukça şişiriyor. Kullanmanın herhangi bir avantajı düşünemiyorum.
Kısacası:
wchar_t
varsayılanları 4 bayta ayarlandı. gcc, -fshort-wchar
boyutu 2 bayta düşüren ancak std libs ile ikili uyumluluğu bozan bir seçeneğe sahiptir.
UTF-8 değişkeni 1 ila 4 bayttır.
UTF-16, değişken 2 veya 4 bayttır.
UTF-32 4 bayt olarak sabitlenmiştir .
Not: UTF-8, en son kurallara göre 1 ila 6 bayt alabilir: https://lists.gnu.org/archive/html/help-flex/2005-01/msg00030.html
Unicode, her grafik sembolüne benzersiz bir tamsayı değeri atayan tek bir büyük karakter kümesi tanımlar (bu büyük bir basitleştirmedir ve aslında doğru değildir, ancak bu sorunun amaçları için yeterince yakındır). UTF-8/16/32 bunu kodlamanın farklı yollarıdır.
Kısaca, UTF-32 her karakter için 32 bit değerleri kullanır. Bu, her karakter için sabit genişlikli bir kod kullanmalarını sağlar.
UTF-16 varsayılan olarak 16 bit kullanır, ancak bu yalnızca 65k olası karakter sağlar, bu da tam Unicode kümesi için yeterince yakın değildir. Bu yüzden bazı karakterler 16 bitlik değerler kullanır.
UTF-8 varsayılan olarak 8 bit değerleri kullanır, bu da 127 ilk değerin sabit genişlikli tek baytlık karakterler olduğu anlamına gelir (en önemli bit, bunun çok baytlı bir dizinin başlangıcı olduğunu belirtmek için kullanılır, 7 gerçek karakter değeri için bit). Diğer tüm karakterler 4 bayta kadar olan diziler olarak kodlanır (bellek çalışıyorsa).
Bu da bizi avantajlara götürüyor. Herhangi bir ASCII karakteri UTF-8 ile doğrudan uyumludur, bu nedenle eski uygulamaları yükseltmek için UTF-8 yaygın ve açık bir seçimdir. Neredeyse tüm durumlarda, en az belleği kullanır. Öte yandan, bir karakterin genişliği hakkında herhangi bir garanti veremezsiniz. 1, 2, 3 veya 4 karakter genişliğinde olabilir, bu da dize manipülasyonunu zorlaştırır.
UTF-32 zıttır, en fazla belleği kullanır (her karakter 4 bayt genişliğinde sabittir), ancak diğer taraftan, her karakterin bu kesin uzunluğa sahip olduğunu bilirsiniz , bu nedenle dize manipülasyonu çok daha basit hale gelir. Bir dizedeki karakter sayısını, dizenin bayt cinsinden uzunluğundan hesaplayabilirsiniz. Bunu UTF-8 ile yapamazsınız.
UTF-16 bir uzlaşmadır. Çoğu karakterin sabit genişlikli 16 bit değerine sığmasını sağlar . Çince sembolleriniz, müzik notalarınız veya başkaları olmadığı sürece, her karakterin 16 bit genişliğinde olduğunu varsayabilirsiniz. UTF-32'den daha az bellek kullanır. Ama bu bazı açılardan "her iki dünyanın en kötüsüdür". Neredeyse her zaman UTF-8'den daha fazla bellek kullanır ve yine de UTF-8'i (değişken uzunluklu karakterler) rahatsız eden problemden kaçınmaz.
Son olarak, platformun desteklediği şeylerle gitmek genellikle yararlıdır. Windows dahili olarak UTF-16 kullanır, bu nedenle Windows'da bu bariz bir seçimdir.
Linux biraz değişiyor, ancak Unicode uyumlu her şey için genellikle UTF-8 kullanıyorlar.
Yani kısa cevap: Üç kodlama da aynı karakter kümesini kodlayabilir, ancak her karakteri farklı bayt dizileri olarak temsil ederler.
Unicode bir standarttır ve UTF-x hakkında bazı pratik amaçlar için teknik bir uygulama olarak düşünebilirsiniz:
Blog yazımda basit bir açıklama yapmaya çalıştım .
herhangi bir karakteri kodlamak için 32 bit (4 bayt) gerekir . Örneğin, bu şemayı kullanarak "A" karakter kod noktasını temsil etmek için, 32 bit ikili sayıya 65 yazmanız gerekir:
00000000 00000000 00000000 01000001 (Big Endian)
Daha yakından bakarsanız, ASCII şemasını kullanırken en sağdaki yedi bitin aslında aynı bitler olduğunu göreceksiniz. Ancak UTF-32 sabit genişlik şeması olduğundan , üç ek bayt daha eklemeliyiz. Diğer bir deyişle, yalnızca "A" karakterini içeren iki dosyamız varsa, biri ASCII kodlu diğeri UTF-32 kodlu ise, boyutu buna göre 1 bayt ve 4 bayt olacaktır.
Birçok kişi UTF-32 kod noktasını temsil etmek için sabit genişlik 32 bit kullandığından UTF-16'nın sabit genişlik 16 bit olduğunu düşünür. YANLIŞ!
UTF-16'da kod noktası 16 bit veya OR 32 bit olarak gösterilebilir. Yani bu şema değişken uzunluklu kodlama sistemidir. UTF-32'ye göre avantajı nedir? En azından ASCII için, dosyaların boyutu orijinalin 4 katı olmayacaktır (ancak yine de iki kez), bu yüzden hala ASCII geriye dönük olarak uyumlu değiliz.
7 bitlik "A" karakterini temsil etmek için yeterli olduğundan artık UTF-32 gibi 4 yerine 2 bayt kullanabiliriz. Şöyle görünecektir:
00000000 01000001
Doğru tahmin ettiniz .. UTF-8'de kod noktası 32, 16, 24 veya 8 bit kullanılarak temsil edilebilir ve UTF-16 sistemi olarak bu da değişken uzunluklu kodlama sistemidir.
Son olarak "A" yı ASCII kodlama sistemini kullanarak temsil ettiğimiz şekilde temsil edebiliriz:
01001101
Çince "語" harfini düşünün - UTF-8 kodlaması:
11101000 10101010 10011110
UTF-16 kodlaması daha kısa olsa da:
10001010 10011110
Temsili ve nasıl yorumlandığını anlamak için orijinal yayını ziyaret edin.
UTF-8, karakterlerin çoğunluğu CJK (Çince, Japonca ve Korece) karakter alanından olmadıkça en fazla yer tasarrufu sağlayacaktır.
UTF-32 karakter baytına göre bir bayt dizisine rastgele erişim için en iyisidir.
0xxxxxxx
ikili olarak forma sahiptir. Tüm iki baytlık karakterler 110xxxxx
ikinci bir bayt ile başlar 10xxxxxx
. Diyelim ki iki baytlık bir karakterin ilk karakteri kayboldu. Gördüğünüz gibi kısa sürede 10xxxxxx
bir önceki olmadan 110xxxxxx
, bir bayt kayıp veya bozuk ve atma olduğunu kesin belirleyebilmesi yeniden geçerli bir ilk bayt görene kadar üzerinde ve hareket karakteri (bir sunucu veya ne olursa olsun ya da yeniden isteği onu) .
MySQL'de UTF-8 ve UTF-16 arasındaki veritabanı performansını karşılaştırmak için bazı testler yaptım.
UTF-32'de tüm karakterler 32 bit ile kodlanır. Avantajı, dizenin uzunluğunu kolayca hesaplayabilmenizdir. Dezavantajı, her ASCII karakteri için fazladan üç bayt harcamanızdır.
UTF-8 karakterleri değişken uzunluktadır, ASCII karakterleri bir baytta (sekiz bit) kodlanır, çoğu batı özel karakteri iki bayt veya üç bayt olarak kodlanır (örneğin € üç bayttır) ve daha egzotik karakterler alabilir dört bayta kadar. Açık dezavantajı, bir priori dize uzunluğunu hesaplayamazsınız. Ancak, Latin (İngilizce) alfabe metnini UTF-32'ye göre kodlamak çok daha az bayt alır.
UTF-16 da değişken uzunluktadır. Karakterler iki bayt veya dört bayt olarak kodlanır. Gerçekten anlamýyorum. Değişken uzunlukta olmanın dezavantajı vardır, ancak UTF-8 kadar yer tasarrufu avantajı yoktur.
Bu üç taneden açıkça UTF-8 en yaygın olanıdır.
Geliştirme ortamınıza bağlı olarak, dize veri türünüzü hangi kodlamanın dahili olarak kullanacağını seçme şansınız bile olmayabilir.
Ancak veri depolamak ve veri alışverişi yapmak için, eğer seçiminiz varsa, daima UTF-8 kullanırım. Çoğunlukla ASCII verileriniz varsa, her şeyi kodlayabilirken, size aktarılacak en düşük miktarda veri verir. En az I / O için optimizasyon, modern makinelere gitmenin yoludur.
Belirtildiği gibi, fark esas olarak altta yatan değişkenlerin boyutudur ve her durumda daha fazla karakterin temsil edilmesine izin vermek için büyür.
Bununla birlikte, yazı tipleri, kodlama ve şeyler çok karmaşıktır (gereksiz mi?), Bu nedenle daha ayrıntılı olarak doldurmak için büyük bir bağlantıya ihtiyaç vardır:
http://www.cs.tut.fi/~jkorpela/chars.html#ascii
Hepsini anlamayı beklemeyin, ancak daha sonra sorun yaşamak istemiyorsanız, olabildiğince erken öğrenmeye değer (ya da sadece sizin için başka birini çözmesini sağlayın).
Paul.
Kısacası, UTF-16 veya UTF-32 kullanmanın tek nedeni sırasıyla İngilizce ve eski komut dosyalarını desteklemektir.
Herkes web / programlama amaçları için açıkça daha verimli olduğunda neden UTF-8 olmayan kodlama seçti merak ediyordum.
Yaygın bir yanlış anlama - son eklenmiş sayı, kapasitesinin bir göstergesi DEĞİLDİR. Hepsi tam Unicode'u destekler, sadece UTF-8 ASCII'yi tek bir baytla işleyebilir, bu yüzden CPU ve internet üzerinden DAHA verimli / daha az bozulabilir.
Bazı iyi okumalar: http://www.personal.psu.edu/ejp10/blogs/gotunicode/2007/10/which_utf_do_i_use.html ve http://utf8everywhere.org