2008-10-14 16 views
6

Jaka jest różnica między UTF i UCS.Użycie UTF w kodzie C++

Jakie są najlepsze sposoby reprezentowania nie europejskich zestawów znaków (przy użyciu UTF) w łańcuchach C++. Chciałbym znać swoje zalecenia dla:

  • wewnętrzna reprezentacja wewnątrz kodu
    • na łańcuchach w czasie wykonywania
    • Za pomocą znaków do celów wystawowych.
  • Najlepsza reprezentacja przechowywania (tj W pliku)
  • Najlepszy formatu transportowego drut (transfer między aplikacji, które mogą być na różnych architekturach i mają inną standardową locale)

Odpowiedz

8

Jaka jest różnica między UTF i LUW.

Kodowanie UCS ma ustaloną szerokość i jest oznaczane liczbą bajtów dla każdego znaku. Na przykład UCS-2 wymaga 2 bajtów na znak. Znaki z punktami kodowania poza dostępnym zakresem nie mogą być zakodowane w kodowaniu UCS.

Kodowanie UTF ma zmienną szerokość i jest oznaczone minimalną liczbą bitów do zapisania znaku. Na przykład kodowanie UTF-16 wymaga co najmniej 16 bitów (2 bajty) na znak. Znaki z dużymi punktami kodowania są kodowane przy użyciu większej liczby bajtów - 4 bajty dla znaków astralnych w UTF-16.

  • wewnętrzna reprezentacja wewnątrz kodu
  • Najlepsza reprezentacja przechowywania (tj W pliku)
  • Najlepszy formatu transportowego drut (transfer pomiędzy aplikacją, która może być na różnych architekturach i mają inny standardowego locale)

Dla nowoczesnych systemów, najbardziej sensowne kodowanie w pamięci i transporcie to UTF-8. Istnieją specjalne przypadki, w których inne mogą być odpowiednie - UTF-7 dla starych serwerów pocztowych, UTF-16 dla słabo napisanych edytorów tekstu - ale najczęściej występuje UTF-8.

Preferowana reprezentacja wewnętrzna zależy od platformy. W systemie Windows jest to UTF-16. W systemie UNIX to UCS-4. Każdy ma swoje zalety:

  • Ciągi UTF-16 nigdy nie używają więcej pamięci niż ciąg UCS-4. Jeśli przechowujesz wiele dużych ciągów znaków ze znakami głównie w podstawowej płaszczyźnie wielojęzycznej (BMP), UTF-16 będzie wymagać o wiele mniej miejsca niż UCS-4. Poza BMP będzie korzystać z tej samej kwoty.
  • UCS-4 jest łatwiejsze do zrozumienia. Ponieważ znaki UTF-16 mogą być podzielone na wiele "par zastępczych", może to być trudne, aby poprawnie podzielić lub wyrenderować ciąg znaków. Tekst UCS-4 nie ma tego problemu. UCS-4 działa podobnie jak tekst ASCII w tablicach "char", więc istniejące algorytmy tekstowe można łatwo przenosić.

Wreszcie niektóre systemy używają formatu UTF-8 jako formatu wewnętrznego. Jest to dobre, jeśli potrzebujesz współdziałać z istniejącymi systemami opartymi na ASCII lub ISO-8859, ponieważ NULL nie zawiera bajtów w środku tekstu UTF-8 - są one w UTF-16 lub UCS-4.

+1

Nie, kodowanie UTF nie zawsze ma zmienną szerokość (na przykład kodowanie UTF-32). – bortzmeyer

+0

Utf-32 może używać stałej szerokości dla każdego punktu kodowania, ale ja * myślę, że * nadal możesz mieć (i musisz zaakceptować i znormalizować jeden punkt kodowy) wiele punktów kodowych (gdy masz połączenie znaków), które reprezentują jeden pełny znak/glif. Jeśli tak, to UTF-32 nie jest tak naprawdę lepszy od UTF-16. – Shadow2531

+1

@bortzmeyer: UTF-32 to tak naprawdę tylko UCS-4 z kilkoma dodatkowymi ograniczeniami. Szczerze mówiąc, nigdy nie widziałem, aby UTF-32 był używany * w dowolnym miejscu *, więc staram się go po prostu zignorować. –

0

UTC jest koordynowany Czas uniwersalny, a nie zestaw znaków (nie znalazłem żadnego zestawu znaków o nazwie UTC).

Dla wewnętrznej reprezentacji, możesz użyć wchar_t dla każdej litery i std :: wstring dla ciągów. Używają dokładnie 2 bajty dla każdej postaci, więc szukanie i losowy dostęp będą szybkie.

W przypadku przechowywania, jeśli większość danych nie jest w formacie ASCII (tj. Kod> = 128), można użyć formatu UTF-16, który jest prawie taki sam jak w przypadku serializacji wstring i wchar_t.

Od UTF-16 może być trochę endian lub big endian, dla transportu drutu, spróbuj przekonwertować go na UTF-8, który jest niezależny od architektury.

+0

Wielkość wchar_t (a więc wewnętrznie nie jest również wstring) nie jest zdefiniowana Widziałem wersje 2 i 4 bajtowe. Dlaczego UTS-16 do przechowywania, ale UTF-8 do plików (Pliki mogą być zapisywane na jednym komputerze i ładowane na innym). Chcę zrozumieć, dlaczego dokonałeś wyboru, a także wyboru. –

+0

http://pl.wikipedia.org/wiki/Universal_Character_Set –

+0

@Martin: UTF-16 nie może być przetwarzany przez istniejące narzędzia zorientowane na ASCII, ponieważ wiele bajtów to 0, co powoduje, że funkcje per-byte uważają, że osiągnięto terminator NULL. –

2

Proponuję:

  • reprezentację w kodzie, wchar_t lub jego odpowiednika.
  • Do reprezentacji pamięci, UTF-8.
  • Do reprezentacji drutu, UTF-8.

Zaletą UTF-8 w sytuacjach przechowywania i przewodów jest to, że nie ma znaczenia endogenność maszyny. Zaletą używania znaku o stałym rozmiarze, takiego jak wchar_t w kodzie, jest to, że można łatwo sprawdzić długość ciągu bez konieczności jego skanowania.

+0

wchar_t: Ale jakie kodowanie? Sugerujesz wewnętrznie kodowanie UTF-16? –

+0

Na wielu platformach Unix wchar_t ma 32 bity, więc jest to łatwe. Na platformach, gdzie wchar_t ma 16 bitów, tak, UTF-16 byłby drogą do zrobienia. –

+0

Martin: Wycofałem twoją edycję, ponieważ użycie wchar_t nie implikuje UTF-16 - w UNIX, sizeof (wchar_t) == 4. –

0

W wewnętrznej reprezentacji wewnątrz kodu, lepiej robić to dla obu bohaterów europejskich i pozaeuropejskich:

\ unnnn

znaków w zakres \ u0020 do \ u007E i odrobiną białych znaków (np. koniec linii) można zapisać jako zwykłe znaki. Wszystko powyżej \ u0080, jeśli napiszesz to jako zwykłą postać, to skompiluje się tylko na twojej stronie kodowej (np. OK we Francji, ale włamanie w Rosji, OK w Rosji, ale włamanie do Japonii, OK w Chinach, ale włamanie do USA, itp. .).