2016-03-26 28 views
6

Ostatnio dużo czytałem na temat kodów Unicode i ich ewolucji z czasem i jestem pewien, że przeczytałem też: http://www.joelonsoftware.com/articles/Unicode.html.Dlaczego Java char używa UTF-16?

Ale coś nie mogłem znaleźć prawdziwy powód, dla którego Java używa UTF-16 dla char.

Na przykład, jeśli miałem ciąg znaków, który zawierał 1024 litery łańcucha znaków ASCII z zakresami znaków. Oznacza to 1024 * 2 bytes, co odpowiada pamięci ciągów o rozmiarze 2KB, które zostanie zużyte w każdym razie.

Jeśli więc Java base char byłby UTF-8, byłby to tylko 1KB danych. Nawet jeśli ciąg ma dowolną cechę, która wymaga 2 bajtów, na przykład 10 znaków "字", naturalnie zwiększy to zużycie pamięci. (1014 * 1 byte) + (10 * 2 bytes) = 1KB + 20 bytes

Rezultat nie jest tak oczywisty. 1KB + 20 bytes VS. 2KB Nie mówię o ASCII, ale moja ciekawość, dlaczego to nie jest UTF-8, który jest po prostu dbaniem o wielobajtowe znaki. UTF-16 wygląda na stratę pamięci w dowolnym ciągu, który ma wiele znaków niebibibych.

Czy istnieje ku temu dobry powód?

+2

Załóżmy, że chcesz uzyskać dostęp do 576. znaku ciągu i jest reprezentowany jako tablica bajtów kodowana w UTF8. Jaki jest koszt operacji? –

+0

hmm, na pewno brakowało mi punktu przeklinania. Musi obliczyć cały bajt X, aby zdecydować, który to jest charachter. Potem postanowili poświęcić pamięć przeciwko procesorowi. – FZE

+1

Ciągi są niezmienne - jest to możliwe (i nadal będzie możliwe doposażenie bez łamania istniejącego * kodu Java * [prawdopodobnie zrywałoby JNI]) do przechowywania łańcuchów zawierających tylko kody 0-255 w 8-bitowym kodowaniu, oraz łańcuchy z innymi kodami w 16-bitowym stylu są teraz. Ale wydaje się, że potrzeba tego nie jest bardzo wysoka (przynajmniej nie widziałem dużego zapotrzebowania na to). –

Odpowiedz

0

Jednym z powodów jest charakterystyka wykonania losowego dostępu lub kolejno po znaków łańcucha znaków:

UTF-8 kodowania wykorzystuje zmienną liczbę (1-4) bajtów do kodowania char UNICODE. Dlatego dostęp do znaku według indeksu: String.charAt(i) byłby o wiele bardziej skomplikowany do wdrożenia i wolniejszy niż dostęp do tablicy używany przez java.lang.String.

+6

Dotyczyło to UCS-2, ale UCS-2 przestał być po rozszerzeniu Unicode poza BMP (tj. Poza pierwsze 65536 znaków); obecnie jest tylko UTF-16 i jest to kodowanie o zmiennej długości dokładnie tak jak UTF-8. Możesz umieścić głowę pod piaskiem i uważać, że iterujesz po punktach kodu Unicode tylko do momentu znalezienia pierwszej zastępczej pary. Zobacz odpowiedź @ nj_ dla szczegółów. –

+0

@MatteoItalia Pytanie, dlaczego Java nie używa np. UTF-8 do przechowywania ciągów znaków w celu zaoszczędzenia pamięci w porównaniu do bieżącej implementacji. Moja odpowiedź podała konkretny powód - mianowicie wykonanie dostępu do znaków według indeksu - dlaczego noc UTF-8 nie jest dobrym pomysłem. – wero

+2

chodzi o to, że UTF-16 to * też * kodowanie o zmiennej długości. –

20

Java używana UCS-2 przed przejściem przez UTF-16 w 2004/2005. Powodem pierwotnego wyboru UCS-2 jest mainly historical:

Unicode został pierwotnie zaprojektowany jako 16-bitowe kodowanie znaków o stałej szerokości. Pierwotny typ danych char w języku programowania Java miał na celu skorzystanie z tego projektu poprzez zapewnienie prostego typu danych, który mógłby pomieścić dowolny znak.

To i narodziny UTF-16 jest dodatkowo explained by the Unicode FAQ page:

Początkowo Unicode został zaprojektowany jako czystego kodowania 16-bitowego, którego celem jest reprezentowanie wszystkich nowoczesnych skryptów. (Starożytne skrypty miały być reprezentowane przez znaki prywatne). Z biegiem czasu, a zwłaszcza po dodaniu ponad 14.500 znaków złożonych w celu zachowania kompatybilności ze starszymi zestawami, stało się jasne, że 16-bitów nie było wystarczających dla społeczności użytkowników. Z tego powstało UTF-16.

Jako że @wero ma already mentioned, nie można efektywnie uzyskać dostępu losowego za pomocą UTF-8. Więc wszystkie rzeczy ważyły ​​się, UCS-2 był pozornie najlepszym wyborem w tym czasie, szczególnie, że na tym etapie nie przydzielono żadnych dodatkowych postaci. To pozostawiło UTF-16 jako najłatwiejszy naturalny postęp.

+2

utf-16 jest jednak wciąż zmienny. Każda postać ma 16 lub 32 bity. Tak więc dostęp losowy w rzeczywistości nie różni się w utf-16 ... jest bezpieczniejszy dla większej ilości postaci. Dostęp losowy nadal nie jest możliwy, jeśli używasz ciągu znaków zawierającego znaki, które używają 2 punktów kodowych –

+0

@CedricMamo: przepraszam, punkt na dostępie losowym był w odniesieniu do UCS-2, a nie UTF-16, a więc komentarz o dodatkowych znakach. Zmienię to na bardziej jednoznaczne, widzę, dlaczego byłby interpretowany w ten sposób. –