Bir Unicode karakteri kaç bayt alır?


239

Kodlamalar konusunda biraz kafam karıştı. Bildiğim kadarıyla eski ASCII karakterleri karakter başına bir bayt aldı. Unicode karakteri kaç bayt gerektirir?

Bir Unicode karakterinin herhangi bir dilden mümkün olan her karakteri içerebileceğini varsayıyorum - doğru muyum? Karakter başına kaç bayta ihtiyaç var?

UTF-7, UTF-6, UTF-16 vb. Ne anlama geliyor? Unicode'un farklı sürümleri mi?

Unicode hakkındaki Wikipedia makalesini okudum ama benim için oldukça zor. Basit bir cevap görmek için sabırsızlanıyorum.



15
Üzgünüm, basit bir cevap yok. Her şeyi biraz dağınık buluyorum. Unicode, iki bayt kullanarak ve tüm karakterleri temsil edebildiği için faturalandırıldı, ancak iki bayt yeterli değildi.
Jonathan Wood

12
"Basit cevap": Unicode karakter 1-4 bayt alır. Unicode pek çok dili kapsar ancak hepsini kapsamaz. Son baktığımda, örneğin Klingon resmi bir Unicode karakter seti değildi.
Peter G.Mar

9
Klingon, Unicode standardının kendisinin bir parçası değil, hayır. Bunun yerine Uniode'un Özel Kullanım Alanını (U + F8D0 - U + F8FF) kullanır.
Remy Lebeau

1
Kurtarıcı soru - teşekkürler. Durumum SCORM 1.2 uyumlu LMS'ler aracılığıyla veri depolamak ... SCORM 1.2 'cmi.suspend_data' standardı, önceki bir geliştiricinin 4096 karakter depolayabileceğimizi düşündüğü 4096 bayt veri. Ah adam yanılmıştı - yer imimizin uzun kurslarda neden başarısız olduğunu keşfettim. Artık biliyorum ki UTF-8 kullandığımız için karakter başına 4 bayt bize 1024 karakter veriyor.
danjah

Yanıtlar:


147

Basit bir cevap görmeyeceksiniz çünkü bir cevap yok.

İlk olarak, Unicode "her dilden her karakteri" içermiyor, ancak kesinlikle deniyor.

Unicode'un kendisi bir eşlemedir, kod noktalarını tanımlar ve kod noktası genellikle bir karakterle ilişkili bir sayıdır . Genellikle diyorum ki karakterleri birleştirmek gibi kavramlar var. Aksanlar veya umlautlar gibi şeylere aşina olabilirsiniz. Bunlar, yeni bir mantıksal karakter oluşturmak için a aveya a gibi başka bir karakterle kullanılabilir u. Bu nedenle bir karakter 1 veya daha fazla kod noktasından oluşabilir.

Hesaplama sistemlerinde faydalı olabilmek için bu bilgiler için bir temsil seçmeliyiz. Bunlar utf-8, utf-16le, utf-32 vb. Gibi çeşitli unicode kodlamalarıdır. Bunlar büyük ölçüde kod birimlerinin boyutu ile ayırt edilirler. UTF-32 en basit kodlamadır, 32 bitlik bir kod birimine sahiptir, bu da bireysel bir kod noktasının bir kod birimine rahatça uyduğu anlamına gelir. Diğer kodlamalarda, bir kod noktasının birden fazla kod birimine ihtiyaç duyacağı veya belirli bir kod noktasının kodlamada hiç temsil edilemediği durumlar olacaktır (bu, örneğin UCS-2 ile ilgili bir sorundur).

Karakterleri birleştirme esnekliği nedeniyle, belirli bir kodlamada bile karakter başına bayt sayısı karaktere ve normalleştirme formuna bağlı olarak değişebilir. Bu, birden fazla temsili olan karakterlerle uğraşmak için bir protokoldür "an 'a' with an accent"(hangisinin bir birleştirici karakter veya "accented 'a'"bir kod noktası olan 2 kod noktası olduğunu söyleyebilirsiniz ).


1
TAMAM. O zaman kaç bayt, verilen bir kod noktasında temsil edilen bir karakteri alır? Örneğin, kırılmayan alan.
Nicolas Barbulesco

UTF8 dizilerinde strlen (), substr () ve diğer dize düzenleme işlevleri yazmak söz konusu olduğunda, birleştirici karakterler bir programcının hayatını cehenneme çevirir. Bu tür işler asla tamamlanmayacak ve her zaman buggy olmayacaktır.
Nulik

Her kodlamayla yorumlanmış Windows-1252, UTF8 ve UTF8-BOM kodlu dosyaları gösteren ve sonuçlar arasındaki eşitliği karşılaştıran bir demo yazdım: github.com/vladyrn/encodings_demo
Vlad

195

Garip bir şekilde, hiç kimse bir Unicode karakterini kaç bayt aldığını nasıl hesaplayacağına dikkat çekmedi. UTF-8 kodlu dizeler için kural şöyledir:

Binary    Hex          Comments
0xxxxxxx  0x00..0x7F   Only byte of a 1-byte character encoding
10xxxxxx  0x80..0xBF   Continuation byte: one of 1-3 bytes following the first
110xxxxx  0xC0..0xDF   First byte of a 2-byte character encoding
1110xxxx  0xE0..0xEF   First byte of a 3-byte character encoding
11110xxx  0xF0..0xF7   First byte of a 4-byte character encoding

Bu yüzden hızlı cevap: birincisine bağlı olarak 1 ila 4 bayt alır, bu da kaç bayt alacağını gösterecektir.


8
4 baytlık bir karakter için maksimum Hex değeri 0xF7 (0xF4 değil) olduğuna inanıyorum.
DJPJ

Çok teşekkür ederim! Ben sadece IETF standardında kontrol + f'ing yapıyordum ve kodlama hakkında hiçbir şey bulamadım ve okuduğum makale, sondaki kod sayısını temsil etmek için kaç bitin kullanıldığını anlatmak için yeterli ayrıntıya girmedi "karakter" başına puan.
MarcusJ

1
Bu şimdi komik ilk iki yorum ile birlikte "yeni ekip üyeleri için giriş" hile sayfasının ikinci sayfasında
Cee McSharpface 15:17

1
0xF4 bir hata değil, bir açıklamadır. Unicode kod noktaları 0-0x10ffff aralığındadır, bu nedenle son kod noktası F4 8F BF BF olarak kodlanır.
Frediano Ziglio

38

Bu sorunun eski olduğunu ve zaten kabul edilmiş bir cevabı olduğunu biliyorum, ancak birkaç örnek sunmak istiyorum (birisine faydalı olacağını umuyorum).

Bildiğim kadarıyla eski ASCII karakterleri karakter başına bir bayt aldı.

Sağ. Aslında, ASCII 7 bit kodlama olduğundan 128 kodu (95'i yazdırılabilir) destekler, bu nedenle yalnızca yarım bayt kullanır (bu bir anlam ifade ediyorsa).

Unicode karakteri kaç bayt gerektirir?

Unicode karakterleri kod noktalarıyla eşleştirir. Bunların nasıl kodlanacağını tanımlamaz. Bir metin dosyası Unicode karakterler içermez, ancak Unicode karakterleri temsil edebilecek bayt / oktetler içerir.

Bir Unicode karakterinin herhangi bir dilden mümkün olan her karakteri içerebileceğini varsayıyorum - doğru muyum?

Hayır. Ama neredeyse. Temel olarak evet. Ama yine de hayır.

Karakter başına kaç bayta ihtiyaç var?

2. sorunuzla aynı.

Ve UTF-7, UTF-6, UTF-16 vb. Ne anlama geliyor? Bir çeşit Unicode sürümü var mı?

Hayır, kodlamalar bunlar. Bayt / sekizlilerin Unicode karakterlerini nasıl temsil etmesi gerektiğini tanımlarlar.

Birkaç örnek. Bunlardan bazıları tarayıcınızda görüntülenemiyorsa (büyük olasılıkla yazı tipi bunları desteklemediğinden), bir resim görmek için http://codepoints.net/U+1F6AA( 1F6AAonaltılık kod noktasıyla değiştirin ) seçeneğine gidin.

    • U + 0061 LATİN KÜÇÜK MEKTUP A: a
      • Nº: 97
      • UTF-8: 61
      • UTF-16: 00 61
    • U + 00A9 TELİF HAKKI İŞARETİ: ©
      • Nº: 169
      • UTF-8: C2 A9
      • UTF-16: 00 A9
    • U + 00AE KAYITLI İŞARET: ®
      • Nº: 174
      • UTF-8: C2 AE
      • UTF-16: 00 AE
    • U + 1337 ETİYOPİK HAZIR PHWA:
      • Nº: 4919
      • UTF-8: E1 8C B7
      • UTF-16: 13 37
    • U + 2014 EM DASH:
      • Nº: 8212
      • UTF-8: E2 80 94
      • UTF-16: 20 14
    • MİLENİN İŞARETİ BAŞINA U + 2030:
      • N: 8240
      • UTF-8: E2 80 B0
      • UTF-16: 20 30
    • U + 20AC EURO İŞARETİ:
      • Nº: 8364
      • UTF-8: E2 82 AC
      • UTF-16: 20 AC
    • U + 2122 TİCARET İŞARETİ İŞARETİ:
      • Nº: 8482
      • UTF-8: E2 84 A2
      • UTF-16: 21 22
    • U + 2603 KARDAN ADAM:
      • N: 9731
      • UTF-8: E2 98 83
      • UTF-16: 26 03
    • U + 260E SİYAH TELEFON:
      • N: 9742
      • UTF-8: E2 98 8E
      • UTF-16: 26 0E
    • YAĞMUR DAMLASI İLE U + 2614 ŞEMSİYE:
      • N: 9748
      • UTF-8: E2 98 94
      • UTF-16: 26 14
    • U + 263A BEYAZ GÜLÜMSEME YÜZÜ:
      • No: 9786
      • UTF-8: E2 98 BA
      • UTF-16: 26 3A
    • U + 2691 SİYAH BAYRAK:
      • Nº: 9873
      • UTF-8: E2 9A 91
      • UTF-16: 26 91
    • U + 269B ATOM SEMBOLÜ:
      • N: 9883
      • UTF-8: E2 9A 9B
      • UTF-16: 26 9B
    • U + 2708 UÇAK:
      • N: 9992
      • UTF-8: E2 9C 88
      • UTF-16: 27 08
    • U + 271E GÖLGELİ BEYAZ LATİN ÇAPRAZ:
      • Nº: 10014
      • UTF-8: E2 9C 9E
      • UTF-16: 27 1E
    • U + 3020 POSTA İŞARETİ YÜZÜ:
      • Nº: 12320
      • UTF-8: E3 80 A0
      • UTF-16: 30 20
    • U + 8089 CJK UNIFIED İDEOGRAF-8089:
      • No: 32905
      • UTF-8: E8 82 89
      • UTF-16: 80 89
    • U + 1F4A9 POO Yığını: 💩
      • N: 128169
      • UTF-8: F0 9F 92 A9
      • UTF-16: D8 3D DC A9
    • U + 1F680 ROKET: 🚀
      • No: 128640
      • UTF-8: F0 9F 9A 80
      • UTF-16: D8 3D DE 80

Tamam taşınıyorum ...

Eğlenceli gerçekler:


Kod birimleri UTF-16 16 bit genişliğindedir. Onlara ortada yanıltıcı olan bir alan gösterdiniz. © için UTF-16 temsili 00A9yerine 00 A9(UTF-16BE olacaktır) olmalıdır.
Roland Illig

Fark ne? BE endian endian değil mi? Büyük endian dilinde yazdı ve bu yüzden büyük endian UTF-16'da yazılmış bir dosya UTF-16BE ile aynı olurdu, değil mi?
HappyPandaFace

6
Düzeltmeler: 1) ASCII 7 bit, bir bayt 8 bittir, bu yüzden yarıdan çok daha fazladır. 2) Unicode kod noktalarının nasıl kodlanacağını tanımlar. UTF-8, UTF-16 ve UTF-32, Unicode Standardında tanımlanmıştır.
Jonathan Rosenne

3
@JonathanRosenne Sanırım 8 bit ile temsil edilen olası değerlerin sadece yarısını kullanıyor, bitlerin yarısını değil.
Aritz Lopez

2
Örnekleri gerçekten seviyorum. Örneğin, UTF-8 yerine neden UTF-16'yı tercih edebileceklerini vurgulamaktadırlar. Farklı yazılım geliştiricileri, Unicode karakterlerin kullanılma olasılığına bağlı olarak farklı kodlamalar seçebilir. Örneğin Çin / Japonya'da UTF-16 (2 bayt) onlar için UTF-8'den daha mantıklıdır, çünkü aynı karakterlerin UTF-8'de kodlamak için genellikle iki kat daha fazla bayta ihtiyacı olacaktır
mike

29

Basitçe söylemek gerekirse Unicode, dünyanın tüm karakterlerine bir sayı (kod noktası denir) atanan bir standarttır (hala devam ediyor).

Şimdi bu kod noktalarını bayt kullanarak temsil etmeniz gerekiyor, buna denir character encoding. UTF-8, UTF-16, UTF-6bu karakterleri temsil etmenin yollarıdır.

UTF-8çok baytlı karakter kodlamasıdır. Karakterler 1 ila 6 bayta sahip olabilir (bazıları şu anda gerekli olmayabilir).

UTF-32 her karakter 4 baytlık bir karakter içerir.

UTF-16her karakter için 16 bit kullanır ve BMP adı verilen Unicode karakterlerin sadece bir kısmını temsil eder (tüm pratik amaçlar için yeterlidir). Java bu kodlamayı dizelerinde kullanır.


10
Unicode bir 21 bit kod kümesidir ve UTF-8'deki herhangi bir Unicode karakterini temsil etmek için 4 bayt yeterlidir. UTF-16, BMP (temel çok dilli düzlem) dışındaki karakterleri temsil etmek için suretler kullanır; geçerli bir Unicode karakterini temsil etmek için 2 veya 4 bayt gerekir. UCS-2, BMP dışındaki taşıyıcılar veya karakterler için destek olmadan sadece UTF-16'nın 16-bit varyantıydı.
Jonathan Leffler

1
Haklısın. UTF-8 orijinalinde 32 bit barındırmak için 6 bayt vardı. Aslında zaten wiki doc ile karıştırıldığı gibi şeyleri karmaşıklaştırmak istemedim :)
Zimbabao

3
Bu yanıt UTF-16'nın BMP kod noktalarını kodlayamadığını belirtir. Bunlar, yedek çiftler kullanılarak UTF-8'de olduğu gibi kodlanabileceğinden yanlıştır. (Unicode 2.0 çıkmadan önce, sadece 16 bit kod noktalarını kodlayan eski UCS-2'yi düşünmelisiniz.) Ayrıca Java UTF-16'yı tam olarak kullanmaz, kod noktasının değiştirilmiş bir formunu kullanır 0 farklı kodlanmıştır.
rdb

@rdb - Tam tersi. Cevap UTF-16'nın BMP'yi temsil ettiğini söylüyor.
Nicolas Barbulesco

3
Yanlış yazdım; "BMP olmayan" demek istemiştim. Yanıttaki hata, UTF-16'nın yanlış olan BMP karakterlerini temsil ettiğini söylüyor. UTF-16 tüm unicode karakterleri kodlayabilir - BMP dışı karakterler yedek çiftler tarafından kodlanır. Belki de cevaplayan UCS-2 ile karıştırılmıştır.
rdb

17

UTF-8'de:

1 byte:       0 -     7F     (ASCII)
2 bytes:     80 -    7FF     (all European plus some Middle Eastern)
3 bytes:    800 -   FFFF     (multilingual plane incl. the top 1792 and private-use)
4 bytes:  10000 - 10FFFF

UTF-16'da:

2 bytes:      0 -   D7FF     (multilingual plane except the top 1792 and private-use )
4 bytes:   D800 - 10FFFF

UTF-32'de:

4 bytes:      0 - 10FFFF

10FFFF, tanım gereği son unicode kod noktasıdır ve UTF-16'nın teknik sınırı olduğu için bu şekilde tanımlanır.

Ayrıca UTF-8'in 4 baytta kodlayabildiği en büyük kod noktasıdır, ancak UTF-8'in kodlamasının arkasındaki fikir, 7FFFFFFF'ye kadar kod noktalarını kapsamak için 5 ve 6 bayt kodlamalarda da işe yarar. UTF-32'nin yarısı.


8

Unicode'da cevap kolayca verilmez. Sorun, daha önce de belirttiğiniz gibi kodlamalardır.

Aksan karakterleri olmayan herhangi bir İngilizce cümle göz önüne alındığında, UTF-8'in cevabı karakterler kadar bayt ve UTF-16 için iki kat karakter sayısı olacaktır.

(Şu andan itibaren) boyut hakkında açıklama yapabileceğimiz tek kodlama UTF-32'dir. Kod noktalarının gelecekteki bir UTF-64 için hazırlandığını hayal etsem de, karakter başına her zaman 32bit var :)

Bu kadar zorlaştıran en az iki şeydir:

  1. Zaten aksanlı / aksanlı (À) karakter varlığını kullanmak yerine, kullanıcı aksanı ve temel karakteri (`A) birleştirmeye karar verdi.
  2. kod noktaları. Kod noktaları, UTF kodlamalarının, adlarını veren izin verilen bit sayısından daha fazla kodlamaya izin verdiği yöntemdir. Örneğin, UTF-8, kendi başına geçersiz olan belirli baytları belirtir, ancak geçerli bir devam baytı izlediğinde, 8 bitlik 0,.255 aralığının ötesinde bir karakteri tanımlamaya izin verir. Bkz Örnekler UTF-8 Vikipedi'ye aşağıda ve Çok uzun kodlamalar.
    • Verilen mükemmel bir örnek € karakteri (nokta, orada U+20AColduğu gibi ya da temsil edilebilir , üç baytlık dizinin E2 82 ACveya dört bayt dizisi F0 82 82 AC.
    • Her ikisi de geçerlidir ve bu, cevabın UTF-8 veya UTF-16 gibi belirli bir Unicode kodlaması hakkında değil, "Unicode" hakkında konuşurken ne kadar karmaşık olduğunu gösterir.


4

Ben de Wikipedia sayfasını çektim ve giriş bölümünde "Unicode farklı karakter kodlamaları ile uygulanabilir." En yaygın kullanılan kodlamalar UTF-8'dir (herhangi bir ASCII karakteri için bir bayt kullanır). UTF-8 ve ASCII kodlamalarında aynı kod değerleri ve diğer karakterler için dört bayta kadar), artık kullanılmayan UCS-2 (her karakter için iki bayt kullanır, ancak geçerli Unicode standardındaki her karakteri kodlayamaz) "

Bu alıntıda gösterildiği gibi, probleminiz Unicode'un karakterleri kodlamanın tek bir yolu olduğunu varsaymanızdır. Aslında Unicode'un birden çok formu vardır ve yine bu alıntıda, birisinin alıştığınız gibi karakter başına 1 bayt bile vardır.

Yani istediğiniz basit cevabınız değişiyor.


3

UTF-16 için, 0xD800 veya daha büyük bir karakterle başlıyorsa, karakterin dört bayta (iki kod birimi) ihtiyacı vardır; böyle bir karaktere "vekil çifti" denir. Daha spesifik olarak, bir vekil çift şu forma sahiptir:

[0xD800 - 0xDBFF]  [0xDC00 - 0xDFF]

burada [...], verilen aralığa sahip iki baytlık bir kod birimini belirtir. <= 0xD7FF olan her şey bir kod birimidir (iki bayt). > = 0xE000 olan herhangi bir şey geçersiz (muhtemelen BOM işaretçileri hariç).

Bkz. Http://unicodebook.readthedocs.io/unicode_encodings.html , bölüm 7.5.



1

Wiki'den:

ASCII ile uyumluluğu en üst düzeye çıkaran 8 bitlik değişken genişlikli kodlama UTF-8;

UTF-16, 16 bit, değişken genişlikte kodlama;

UTF-32, 32 bit, sabit genişlikli kodlama.

Bunlar en popüler üç farklı kodlamadır.

  • UTF-8'de her karakter 1 ila 4 bayta kodlanır (baskın kodlama)
  • UTF16'da her karakter 1 ila iki 16 bit kelimeye kodlanır ve
  • UTF-32'de her karakter tek bir 32 bit sözcük olarak kodlanır.

1

Unicodeher karakter için benzersiz bir sayı sağlayan bir standarttır . Bu benzersiz sayılara code pointdünyadaki tüm karakterlere s (sadece benzersiz kod olan) denir (bazıları hala eklenecektir).

Farklı amaçlar için, bunu code pointsbayt cinsinden göstermeniz gerekebilir (çoğu programlama dili bunu yapar) ve işte burada Character Encodingdevreye girer.

UTF-8, UTF-16, UTF-32Ve benzeri hepsi Character Encodingsve Unicode'un kod noktaları farklı şekillerde, bu kodlamaların temsil edilir.


UTF-8 kodlama değişken genişlikte bir uzunluğa sahiptir ve içinde kodlanan karakterler, 1 ila 4 bayt dahil olabilir;

UTF-16değişken bir uzunluğa sahiptir ve içinde kodlanmış karakterler 1 veya 2 bayt (8 veya 16 bit) alabilir. Bu, BMP (Temel Çok Dilli Düzlem) adı verilen tüm Unicode karakterlerin yalnızca bir bölümünü temsil eder ve neredeyse tüm durumlar için yeterlidir. Java UTF-16, dizeleri ve karakterleri için kodlama kullanır ;

UTF-32 sabit bir uzunluğa sahiptir ve her karakter tam olarak 4 bayt (32 bit) alır.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.