Soru Java, 16 bit char türünde UTF-16 karakterlerini nasıl depolar?


Göre Java SE 7 ÖzellikleriJava, karakterleri göstermek için Unicode UTF-16 standardını kullanır. Hayal ederken String olarak basit dizi Her biri bir karakter içeren 16 bitlik değişkenlerin ömrü basittir.

Ne yazık ki, 16 bitin yeterli olmadığı kod noktaları vardır (tüm Unicode karakterlerin 16 / 17'si olduğuna inanıyorum). Yani bir String, bu doğrudan bir sorun teşkil etmez, çünkü bu ~ 1.048.576 karakterinden birini saklamak istendiğinde ek iki bayt, sadece iki dizi pozisyonları String kullanılacaktır.

Bu, hiç poz vermeden direkt sorun, için çalışıyor Strings, çünkü her zaman ek iki bayt olabilir. UTF-16 kodlamasının aksine, tek değişkenler söz konusu olduğunda 16 bitlik sabit uzunlukBu karakterler nasıl saklanabilir, özellikle de Java nasıl yapılır? 2 baytlık "char" tipi?


22
2017-10-28 19:57


Menşei


Lütfen backtickleri kötüye kullanmayın. Onlar için kod bir tek. - Kerrek SB
Olmaz .. Bir nokta kadar saklayabilirse, 'karakter' olarak adlandırırlardı :) Dize [indeks] geçersiz bir karakter olabilir. Daha fazla bilgi utf8everywhere.org. - Pavel Radzivilovsky
@KerrekSB Peki, her zaman, en önemlisi ya da yüksek bir tanıma değerine sahip olan kelimeleri ya da kalıpları vurgulamak ya da vurgulamak için kullandım. Fakat beni doğru yaptığınız için teşekkürler, gelecekte daha dikkatli olmaya çalışacağım. - Kierrow
@Kierrow: Normal ve olağanüstü vurgu için italik ve kalın yüzü kullanabilirsiniz. Bu çoğu SO mesaj için yeterli olmalı! :-) - Kerrek SB


Cevaplar:


Cevap içeride javadoc :

Char veri türü (ve dolayısıyla bir Character nesnesinin değeri   Kapsüller) orijinal Unicode belirtimine dayanır.   tanımlı karakterleri sabit genişlikli 16 bit varlıklar olarak. Unicode   standart,   temsil 16'dan fazla biti gerektirir.

Yasal kod aralığı   noktalar şimdi U + 0000 ila Unicode skaler değeri olarak bilinen U + 10FFFF'dir.   (Unicode standardındaki U + n notasyonunun tanımına bakınız.)   U + 0000'den U + FFFF'ye kadar olan karakter kümesine bazen   Temel Çok Dilli Düzlem (BMP) olarak. Kod noktalarını gösteren karakterler   U + FFFF'den daha büyük olanlar ek karakterler olarak adlandırılır. Java   2 platform char dizilerinde UTF-16 gösterimini kullanır ve   Dize ve StringBuffer sınıfları. Bu sunumda, tamamlayıcı   karakterleri bir çift char değerleri olarak temsil edilir.   yüksek vekil aralığı, (\ uD800- \ uDBFF), ikincisi   düşük vekil aralığı (\ uDC00- \ uDFFF).

Bu nedenle bir char değeri   dahil olmak üzere Temel Çok Dilli Düzlem (BMP) kod noktalarını gösterir.   kodlama kod noktaları veya UTF-16 kodlamanın kod birimleri. Bir int   değer, ek kod dahil olmak üzere tüm Unicode kod noktalarını temsil eder   puan. İnt (en az anlamlı) 21 bit int için kullanılır   Unicode kod noktalarını ve üst (en önemli) 11 bit'i temsil eder   sıfır olmalı.

Aksi belirtilmedikçe, ilgili davranış   ek karakterler ve vekil char değerleri şöyledir:   Yalnızca bir char değerini kabul eden yöntemler tamamlayıcıyı destekleyemez   karakter. Char değerlerini vekil aralıklarından ele alırlar.   tanımsız karakterler. Örneğin, Karakter.isLetter ('\ uD840')   herhangi bir kişi tarafından takip edilen bu özel değer olsa bile, false döndürür   Bir dizede düşük vekil değeri bir harfi temsil eder. Metodlar   int değeri kabul eden tüm Unicode karakterleri de dahil olmak üzere   ek karakterler. Örneğin, Karakter.isLetter (0x2F81A)   kod noktası değeri bir harfi (CJK) temsil ettiği için true değerini döndürür   ideogramı). Java SE API belgelerinde Unicode kod noktası   U + 0000 ve U + 10FFFF aralığındaki karakter değerleri için kullanılır,   ve Unicode kod birimi, kod olan 16 bit char değerleri için kullanılır   UTF-16 kodlamanın birimleri. Unicode hakkında daha fazla bilgi için   terminoloji, Unicode Sözlüğüne bakın.

Basitçe söylenmiş :

  • Bir char kuralı için 16 bit, Unicode standardının eski bir sürümü için tasarlanmıştır
  • Temel Çok Dilli Düzlemde olmayan bir unicode rune (kod noktası) göstermek için bazen iki karaktere ihtiyacınız vardır. Bu çeşit "çalışır" çünkü özellikle BMP dışındaki unicode run'ları işlemek için chars kullanmıyorsunuz.

Daha basit dedi ki:

  • Bir java char bir Unicode kod noktasını temsil etmez (iyi, her zaman değil).

Bir kenara bakılırsa, Unicode'un BMP'yi aşarak genişlemesinin evriminin UTF-16'yı küresel olarak alakasız hale getirdiği, şimdi de UTF-16'nın sabit bir bayt-chars oranını bile etkinleştirmediği unutulmamalıdır. Bu yüzden daha modern diller UTF-8'e dayanıyor. Bu bildiri anlamanıza yardımcı olur.


24
2017-10-28 20:00



Ve şu int ch ek karakterleri saklayan, bunu dizenin bir parçası olarak nasıl saklarım? write(int ch) Bu karakteri başka bir dış kaynağa yazmak için kullanılabilir. - overexchange


Temel olarak, dizeler, bir dizi Unicode kod noktasının saklanmasıyla aynı olmayan bir dizi UTF-16 kod birimi depolar.

Temel Çok Dilli Düzlem dışındaki bir karakter gerektiğinde, bu iki UTF-16 kod birimi içine alır. String.

Çoğu String operasyonlar - length(), charAt, substring() vb UTF-16 kod birimleri sayısında anlaşma. Ancak, benzeri işlemler var codePointAt() dizinler hala UTF-16 kod birimleri cinsinden ifade edilmiş olsa da, tam Unicode kod noktaları ile ilgilenecektir.

DÜZENLEME: BMP olmayan kod noktasını tek bir şekilde depolamak istiyorsanız charTemelde şanstan yoksun. Bu, 256'dan fazla farklı değeri bir byte değişken ... sadece işe yaramıyor. Başka bir yerde bir kod noktasını temsil eden sözleşmelerden sonra (ör. String) sadece bir int değişken.


7
2017-10-28 20:01



İlginç ve önemli, ama soru bireysel etrafında daha odaklanmış gibi görünüyor charstring işlemleri yerine (son cümle cümlesinin).
@delnan: Düzenleyecek. - Jon Skeet