Czy kodowanie znaków oprócz UTF-8 (a może UTF-16 / UTF-32) powinno być przestarzałe?

31

Mój wkurzony zwierzak patrzy na tak wiele projektów oprogramowania, które mają góry kodu do obsługi zestawu znaków. Nie zrozum mnie źle, jestem za zgodą i cieszę się, że edytory tekstu pozwalają otwierać i zapisywać pliki w wielu zestawach znaków. Denerwuje mnie to, jak rozprzestrzenianie się nie uniwersalnych kodowań znaków jest oznaczone jako „właściwe wsparcie Unicode”, a nie „problem”.

Na przykład pozwól mi wybrać PostgreSQL i obsługę zestawu znaków . PostgreSQL zajmuje się dwoma typami kodowania:

  • Kodowanie klienta: Używany w komunikacji między klientem a serwerem.
  • Kodowanie na serwerze: służy do wewnętrznego przechowywania tekstu w bazie danych.

Rozumiem, dlaczego obsługa wielu kodowań klientów jest dobra. Umożliwia klientom, którzy nie działają w UTF-8, komunikowanie się z PostgreSQL bez konieczności przeprowadzania konwersji. Nie rozumiem: dlaczego PostgreSQL obsługuje wiele serwerów kodowanie ? Pliki bazy danych (prawie zawsze) są niekompatybilne z jedną wersją PostgreSQL do następnej, więc zgodność między wersjami nie jest tutaj problemem.

UTF-8 to jedyny standardowy zestaw znaków zgodny z ASCII, który może kodować wszystkie punkty kodowe Unicode (jeśli się mylę, daj mi znać). Jestem w obozie, że UTF-8 jest najlepszy zestawem znaków, ale jestem gotów znosić inne uniwersalne zestawy znaków, takie jak UTF-16 i UTF-32.

Uważam, że wszystkie nie uniwersalne zestawy znaków powinny być przestarzałe. Czy jest jakiś ważny powód, dla którego nie powinni?

Joey Adams
źródło
4
@mario: Oryginalna definicja UTF-8 dopuszczała do 6 bajtów. Później został sztucznie ograniczony, aby objąć tylko postacie, które UTF-16 mógł obsługiwać.
dan04
6
Przynajmniej PostgreSQL celowo zajmuje się kodowaniem wielu znaków. Trudno jest mieć do czynienia z przypadkową mieszanką UTF-8 i Windows-1252, ponieważ ktoś po prostu nie dbał.
dan04
5
@ dan04: Praca z tekstami rosyjskimi była uciążliwa, ponieważ korzystały z wielu kodowań, które były zasadniczo różne i zwykle po prostu hackowały różne rzeczy przy użyciu różnych czcionek (co często kłamałoby na temat kodowania używanego w ich metadanych). W sumie okropny bałagan. Podejrzewam jednak, że oczyścili - prawdopodobnie poprzez przejście na UTF-8 - ponieważ liczba zgłoszeń z tego kierunku spadła.
Donal Fellows
3
Teoretyczny zakres Unicode wynosi od 0 do 0x10ffff. Nic więcej. Tak mówi standard Unicode. UTF-8 obsługuje cały Unicode i zawsze tak będzie. Nie obejmuje hipotetycznego zakresu kodowania, które nie jest Unicode, ale obejmuje cały Unicode.
gnasher729

Odpowiedzi:

16

Odkąd wspominałeś o PostgreSQL, mogę z pewnym autorytetem powiedzieć, że głównym zabójczym powodem, dla którego kodowania po stronie serwera inne niż UTF8 są obsługiwane tak szczegółowo, jest to, że Japończycy tego potrzebują. Najwyraźniej identyczna konwersja w obie strony między Unicode a różnymi japońskimi „starszymi” kodowaniami nie zawsze jest możliwa, aw niektórych przypadkach tabele konwersji są nawet różne u różnych dostawców. To naprawdę zaskakujące, ale najwyraźniej tak. (Rozbudowana obsługa zestawu znaków jest również jednym z powodów, dla których PostgreSQL jest tak popularny w Japonii).

Ponieważ mówimy o systemie baz danych, jednym z głównych zadań jest niezawodne przechowywanie i pobieranie danych, zgodnie z definicją użytkownika, więc konwersja stratnego zestawu znaków czasami nie powiedzie się. Jeśli masz do czynienia z przeglądarką internetową, powiedzmy, gdzie naprawdę ważne jest to, czy wynik wygląda dobrze, to prawdopodobnie możesz uniknąć obsługi mniejszego kodowania, ale w systemie baz danych masz dodatkowe wymagania.

Niektóre z innych powodów wymienionych w innych odpowiedziach mają również zastosowanie jako argumenty wspierające. Ale dopóki Japończycy to zawetują, nie można zmniejszyć obsługi konfiguracji postaci.

Peter Eisentraut
źródło
Więc z powodu tych kodowań konwersja tekstu na UTF-8 i odwrotnie jest ogólnie stratna? Nawet jeśli konwersja jest wykonywana natychmiast (a nie za 6 miesięcy)?
Joey Adams
Joey Adams: Najwyraźniej tak.
Peter Eisentraut,
3
Google za „zjednoczenie Hana”, by zobaczyć, dlaczego
Petr Viktorin,
7

Dwa oczywiste powody: w zależności od przechowywanych danych, konwersja do innego formatu może zająć sporo czasu i dodatkowego miejsca. Jeśli przechowujesz 400 megabajtów informacji, podwojenie wymagań dotyczących miejsca to nic wielkiego - ale jeśli przechowujesz 400 terabajtów, zaczyna to oznaczać nieco więcej. Konwersja 400 terabajtów danych z (powiedzmy) Shift-JIS na UTF-x również może zająć trochę czasu.

Staje się to szczególnie trudne, jeśli masz (na przykład) gwarancje bezawaryjności, które mówią, że baza danych będzie dostępna dla wszystkich, ale powiedzmy, 10 minut w danym roku, a baza danych jest aktualizowana kilkaset razy na sekundę. Pamiętaj, że w takiej sytuacji nadal można zarządzać dużymi konwersjami, ale nie jest to coś lekkiego. W niektórych przypadkach przygotowanie się do takiej konwersji może zająć lata .

Jeśli zaczynasz od bazy danych, która (na przykład) obsługuje tylko ASCII, może istnieć dobry powód do debaty, czy warto dodać obsługę wszystkich tych kodowań - ale jeśli już je obsługujesz, niewiele zyskasz porzuceniu wsparcie dla nich.

Zwróć uwagę w szczególności, że prawdopodobnie nie zyskasz prawie nic w celu uproszczenia kodu lub czegoś podobnego. Nadal będą potrzebować wszystkich procedur konwersji, aby poradzić sobie z konwersjami między klientem a serwerem. W związku z tym porzucenie obsługi oznaczałoby porzucenie jednego (mniejszego) wywołania funkcji w ścieżkach „zapisu na dysk” i „odczytu z dysku”, ale niewiele (jeśli cokolwiek innego). Gdybyś wspierał nawet dwa kodowania na dysku, nawet byś tego nie zyskał - nadal miałbyś tam wywołanie funkcji, więc tak naprawdę jedyne, co byś zrobił, to ograniczenie zakresu kodowań obsługiwanych przez tę funkcję.

Przynajmniej gdybym to projektował, prawdopodobnie napisałbym rdzeń bazy danych do pracy w UCS-4, a następnie miałbym procedury konwersji między rdzeniem a dyskiem oraz między rdzeniem a użytkownikiem. W obu przypadkach używałbym tego samego zestawu procedur, więc najprostszą drogą byłoby zezwolenie pamięci dyskowej na używanie dokładnie tego samego zestawu kodowań, z którego mogli korzystać klienci.

Jerry Coffin
źródło
1
Shift-JIS nie jest samosynchronizujący, co utrudnia wyszukiwanie. Ci będzie zdobyć znaczne uproszczenie przez nie wspiera go.
dan04
@ dan04: jeśli masz już sprawdzone procedury wyszukiwania / indeksowania Shift-JIS, przejście na UTF-8 lub nawet UCS2 prawdopodobnie nieznacznie poprawi wydajność. W przypadku nowej bazy danych możesz wybrać lepsze, wygodniejsze i regularniejsze kodowanie, takie jak UCS2 lub UTF-16.
9000
@ dan04: gdybyś mógł uciec, nie wspierając go wcale, zyskałbyś całkiem sporo. Tak długo, jak popierasz to, przychodząc od klientów i przechodząc do nich, będziesz tkwił w większości brzydoty ...
Jerry Coffin
5

Jest kilka problemów z przechowywaniem tylko UTF-8 na serwerze:

  1. Jaki jest limit VARCHAR(20)kolumny? Czy to 20 bajtów, czy 20 „znaków” (a w Unicode, co to jest „znak”, jeśli weźmie się pod uwagę łączenie znaków, ligatur itp.). Co gorsza, co z tym, CHAR(20)gdzie faktycznie musi zarezerwować całą możliwą przestrzeń: Wierzę w MySQL, rezerwuje 4-krotną liczbę bajtów dla kolumny zakodowanej w UTF-8 (czyli 80 bajtów CHAR(20)) tylko na wypadek najgorszego przypadku.
  2. Musisz wykonywać ciągłe konwersje kodowania między kodowaniem serwera a kodowaniem klienta. Możesz argumentować, że chcesz również przestać obsługiwać wiele kodowań klientów, ale jeśli tego nie zrobisz, wszystkie ciągi muszą być cały czas konwertowane. Jeśli możesz dopasować kodowanie serwera i kodowanie klienta, konwersje nie są wymagane.
  3. Jak zauważyli inni, UTF-8 jest dość wydajny do przechowywania tekstu w języku angielskim, ale jest bardzo nieefektywny w przypadku innych języków - w szczególności języków wschodnioazjatyckich. Przypuszczam, że można zezwolić na użycie UTF-16 lub UTF-8 jako garniturów. Lub kompresuj tekst, ale powoduje to, że indeksowanie i wyszukiwanie jest nieefektywne.

Powiedziawszy to wszystko, zgadzam się z tobą: starsze kodowania są w większości bezcelowe, a Unicode jest ogólnie najlepszym kodowaniem do zastosowania we wszystkich nowych aplikacjach. Gdybym dzisiaj pisał serwer bazy danych od podstaw, obsługiwałbym tylko Unicode i nie obsługiwałby w ogóle żadnego starszego kodowania.

Różnica polega na tym, że PostgreSQL i większość innych używanych obecnie serwerów baz danych istniały, zanim Unicode stał się realną opcją. Mieli już wsparcie dla kodowania starszego typu (wtedy oczywiście nie byli starszymi wersjami) i po prostu nie ma sensu wyrywanie całego tego kodu z powodów głównie ideologicznych.

Dean Harding
źródło
10
”, ale jest bardzo nieefektywny w przypadku innych języków - w szczególności języków wschodnioazjatyckich” Nawet w praktyce? Rozważ tę chińską stronę Wikipedii . Mimo że wyświetla okropnie dużo chińskich znaków, w źródle strony znaki ASCII przytłaczają je prawie 7: 1.
Joey Adams,
2
Jeśli N w kolumnie CHAR (N) jest częścią dobrze zdefiniowanego formatu identyfikatora (np. VIN ma dokładnie 17 znaków), prawdopodobnie nie wymaga łączenia znaków ani ligatur. Jeśli nie, to N jest arbitralnym ograniczeniem, które należy interpretować hojnie, aby uniknąć obcięcia danych.
dan04
5
@Joey Adams: dotyczy to HTML i XML, w którym sam znacznik stanowi dużą część tekstu (i dlatego uważam, że UTF-8 jest dobrym wyborem dla Internetu), ale w bazie danych, której często nie przechowujesz HTML. Pod koniec dnia jest to tylko czynnik dwóch (lub mniej) różnic, co tak naprawdę nie jest tak bardzo.
Dean Harding
5
Punktor nr 2 w tej odpowiedzi jest nieistotny: ma zastosowanie niezależnie od tego, czy używany jest Unicode. Punktor nr 3 absolutnie wyolbrzymia nieefektywność i jej zakres. Jednocześnie ta odpowiedź w znacznym stopniu uwzględnia problemy spowodowane przez starsze kodowania. Łatwo jest założyć, że problem nie jest taki duży, jeśli w życiu używasz tylko angielskiego.
Timwi
2
@Dean: Nie wiedziałem, że nie wolno komentować odpowiedzi bez opublikowania własnego.
Timwi
3

Nie-uniwersalne (a konkretnie jednobajtowe) kodowania mają swoje miejsce: w systemach, które:

  • Brak wystarczającej ilości pamięci do przechowywania bazy znaków znaków Unicode.
  • Mieć jednobajtową czcionkę zakodowaną na stałe w pamięci ROM.
  • Nie mają dostępu do Internetu, aby zapewnić źródło plików o różnych kodowaniach.

Tak jest dzisiaj w przypadku niektórych typów urządzeń osadzonych. Ale na pulpicie iw serwerowni kodowania inne niż Unicode powinny być już dawno przestarzałe.

dan04
źródło
3
Kiedyś miałem takie komputery domowe. Pozbyłem się większości z nich na początku lat 80.
David Thornley,
2

UTF-8 jest najlepszy dla Ciebie egocentryczny 1 angielski. Gdybyś był Japończykiem, około 99% twoich postaci zajęłoby 3-4 bajty zamiast dwóch w UTF-16.

Dialekty niełacińskie naprawdę cierpią na UTF-8 na poziomie wielkości. Nie zapominaj, że w ciągu kilku lat większość Twoich klientów może być Chińczykami, a chińskie pismo ma miliony znaków. Z UTF-8 nie da się tego tak skutecznie utrzymać.

W przeciwnym razie, nienawidzę go, gdy mam dokumentów tekstowych, które nie są w UTF- coś . Często zejdę mi z drogi, jeśli muszę mieć odpowiednie kodowanie. W mojej książce kodowania inne niż Unicode są martwe.

1. Nie bierz części egocentrycznej osobiście. Chciałem zrobić kolorową ilustrację i tak naprawdę nie mam tego na myśli.

skradać się
źródło
3
@Matthew - 4x jest wyraźnie 4 razy większy niż x (dla dodatniego x). Nie rozumiem, jak ważny jest tutaj zapis asymptotyczny. Nigdy nie widziałem reklamowanego dysku twardego z asymptotyczną stopą wzrostu. Zwykle rozmiar pozostaje taki sam przez cały okres eksploatacji dysku.
Steve314,
3
Miliony znaków i tak nie zmieszczą się w Unicode. Zgodnie z artykułem z Wikipedii jest obecnie około sześćdziesięciu tysięcy postaci Hana. Ponieważ Unicode nie jest tylko chińskim, oznacza to, że spora liczba chińskich znaków zajmie cztery bajty w UTF-16, czyli tyle, ile obecnie UTF-8. Interesujące byłyby statystyki dotyczące długości chińskich tekstów w UTF-8 i UTF-16.
David Thornley,
6
@David:> 99% wszystkich pism japońskich i chińskich używa znaków wymagających tylko 2 bajtów w UTF-16 i 3 w UTF-8. Postacie, które wymagają więcej, są bardzo rzadkie i / lub historyczne.
Timwi
8
Pamiętaj, że japoński i chiński zazwyczaj używają mniej znaków na słowo. Pracuję z aplikacją, która ma duże pliki językowe w języku angielskim, japońskim i chińskim, wszystkie zakodowane w utf-8. Plik chiński jest w rzeczywistości najmniejszy, podczas gdy plik japoński jest o około 15% większy niż oryginał angielski.
Gort the Robot
3
Nonsens. Wszystko, co zajmuje dwa bajty w UTF-16, nie zajmuje więcej niż 3 bajty w UTF-8. Wszystko, co ma cztery bajty w UTF-8, to 4 bajty w UTF-16. Nie ma „milionów” chińskich znaków i oczywiście nie zmieściłyby się w 16 bitach.
gnasher729
1

Unicode jest zasadniczo zepsuty i prawdopodobnie nie zostanie naprawiony. Musi zostać zastąpiony czymś lepszym, czymś naprawdę uniwersalnym. Jeśli coś wymaga przestarzałości, jest to Unicode.

Przykładowe problemy z Unicide:

  • UTF8 to rozsądny hack, ale większość oprogramowania opartego na UTF16 jest zepsuta. Większość aplikacji Windows obsługujących Unicode używa UTF16, w tym sam system operacyjny. Najczęstszym problemem nie jest obsługa więcej niż płaszczyzny podstawowej, tj. Znaków wielosłówowych.

  • Zjednoczenie Hana to katastrofa nieskrępowana. Niemożliwe jest mieszanie tekstu japońskiego / chińskiego / koreańskiego w jednym dokumencie bez dodatkowych metadanych, a także trudne do wykrycia, której czcionki należy użyć.

  • Znaki kombinacyjne to kolejna katastrofa. Bardziej sensowne schematy kodowania odwzorowują jeden znak na jeden kod, co sprawia, że ​​przetwarzanie ciągów znaków jest względnie rozsądne. Unicode nie. Unicode nie jest nawet spójny - znaki Han są przeważnie kombinacjami, ale nie są zakodowane jako takie, jak w przypadku europejskich znaków kombinacyjnych.

  • Nazwisk niektórych osób nie można poprawnie zapisać w Unicode lub są one bardzo podatne na niepoprawne renderowanie z powodu wyżej wymienionych problemów. Może to mieć poważne konsekwencje, np. Przy próbie wejścia na pokład samolotu z paszportem, który nie pasuje do (nieprawidłowo) wydrukowanego na bilecie.

Ze względu na te i wiele innych problemów wiele nieanglojęzycznych programów nie może używać Unicode i korzysta z lokalnego kodowania znaków. Jest to szczególnie powszechne w przypadku japońskiego i chińskiego oprogramowania.

Idealnie byłoby, gdyby Unicode był przestarzały. Kodowanie znaków TRON jest całkiem dobrym zamiennikiem Unicode i jest w dużej mierze kompatybilne z istniejącym oprogramowaniem, które nie będzie aktualizowane.

użytkownik
źródło
Twoje twierdzenie, że nie można mieszać różnych wariantów znaków (japoński / koreański / chiński) wydaje się być nieaktualne od 15 lat, standard Unicode 3.2 z 2002 r. Unicode obsługuje selektory wariacji, punkty kodowe, które po han kodpunkt wyraźnie określają, która forma powinien zostać wyświetlony. Również znaki kombinatoryczne są określane zarówno jako „łączenie znaków diakrytycznych” ze znakami podstawowymi (a °) i znakami specjalnymi (å), proces konwersji ich na odwrót to „normalizacja”. Więc nie, Unicode nie jest zasadniczo uszkodzony.
Thorsten S.
Zilustrowałeś wiele wad. Niektóre języki używają znaków kombinacyjnych, niektóre nie, a Unicode nie może zdecydować, które preferuje. Jak już wspomniałem, większość oprogramowania, które twierdzi, że obsługuje Unicode i tak nie rozumie tych problemów i wyświetla je nieprawidłowo, nawet w przypadku selektorów. Nie należy oczekiwać, że programiści będą ekspertami językowymi, co jest drugą podstawową wadą Unicode.
użytkownik
0

Może do pisania, ale nie do czytania.

Istnieje wiele istniejących treści, które korzystają z tych kodowań, a niektóre kodowania, takie jak base64, nigdzie się nie wybierają, ponieważ niektóre protokoły tekstowe nakazują takie sposoby osadzania danych binarnych.

Prawdziwym problemem jest automatyczne wykrywanie kodowania, które prowadzi do luk bezpieczeństwa. Nie miałbym nic przeciwko, że niektóre niejasne kodowania, takie jak UTF-7, po prostu znikają.

Automatyczne wykrywanie również źle radzi sobie z treściami wytwarzanymi przez naiwne łączenie ciągów bajtów.

Mike Samuel
źródło
7
Base64 nie jest kodowaniem znaków.
dan04
0

Zgadzam się, że domyślne kodowanie znaków dla baz danych i nowych aplikacji powinno być jakimś wariantem UTF. Ja osobiście wybrałbym UTF-16, ponieważ wydaje się, że jest to rozsądny kompromis w zakresie przestrzeni i złożoności (bardziej niż UTF-8). To powiedziawszy, niektóre kodowania znaków nadal mają sens w niektórych przypadkach.

  • Jeśli przechowujesz / przenosisz tekst base64, potrzebujesz tylko ASCII i możesz nawet uciec z 7-bitowymi zakodowanymi protokołami, takimi jak e-mail. Dodatkowe obciążenie związane z UTF-8 nie jest konieczne.
  • Wiele plików i istniejących danych jest zbudowanych na tych starszych kodowaniach znaków, dlatego umiejętność ich odczytu jest ważna.

Należy pamiętać, że istnieją 4 standardowe algorytmy normalizacji UTF. Jeśli obawiasz się znaków wielopunktowych, możesz użyć jednego z dwóch algorytmów normalizacyjnych, które łączą je w równoważne znaki jednopunktowe. Różnica między nimi dotyczy równoważności logicznej i fizycznej równoważności znaków.

Berin Loritsch
źródło
1
Czy downvoters mogą powiedzieć, dlaczego oddali głos?
Berin Loritsch
3
Nie przegłosowałem, ale sedno base64 polega na przesyłaniu danych binarnych kanałem tekstowym. Jeśli możesz wybrać kodowanie, które chcesz zastosować na tym kanale, w ogóle nie używałbyś kodowania tekstowego. Nawet jeśli twój kanał naprawdę jest zwykłym ASCII, baza 64 używa tylko 6 z 7 bitów - już znaczny narzut.
Steve314,
Mam nadzieję, że ktoś nie tylko przeczytał punktory. Były to wyjątki od używania UTF. I mylisz się co do bazy 64, używając tylko 6 z 8 bajtów. Pierwszy zestaw „znaków” ASCII to niedrukowalne znaki kontrolne, co zmusza niektóre znaki w base64 do użycia 7 z 8 bajtów. Celowo unika się wysokiego bitu, ponieważ nie gwarantuje się, że wszystkie te znaki będą istniały na każdej stronie kodowej, a znaki od 0 do 127.
Berin Loritsch,
2
@Berin - (1) nie, ale to, że „Zgadzam się” nie jest niczym bez punktorów, a (2) podstawa 64 ma 64 „cyfry”. 64 cyfry są warte 6 bitów, ponieważ 2 ^ 6 == 64. Sposób, w jaki reprezentujesz to w 7-bitowej przestrzeni kodowej (lub 8 bitach, a nawet 8 bajtach, jeśli musisz) jest niezależny od ilości faktycznie dostępnych danych. Unikanie znaków niedrukowalnych itp. Jest przyczyną narzutu - nie oznacza to, że narzut nie istnieje. Wybierz kanał przeznaczony dla danych binarnych, a kosztów ogólnych tam nie ma.
Steve314,
3
Pamiętaj, że base64 został wymyślony do obsługi przesyłania danych binarnych kanałem tekstowym. Wiadomo, że jest nieefektywny (rozszerzenie 3: 4), ale zajmuje się ograniczeniami technicznymi niektórych opcji transportu. Starsze byłyby fora e-mail i fora UseNet, ale bardziej nowoczesną aplikacją byłoby osadzanie danych binarnych w formacie XML. Czasami właściwy kanał nie istnieje i musisz przejść przez ograniczenia istniejących.
Berin Loritsch,