Zadam pytanie, które jest prawdopodobnie dość kontrowersyjnym pytaniem: „Czy jedno z najpopularniejszych kodowań, UTF-16, należy uznać za szkodliwe?”
Dlaczego zadaję to pytanie?
Ilu programistów jest świadomych faktu, że UTF-16 jest tak naprawdę kodowaniem o zmiennej długości? Rozumiem przez to, że istnieją punkty kodowe, reprezentowane jako pary zastępcze, biorą więcej niż jeden element.
Wiem; wiele aplikacji, struktur i interfejsów API korzysta z UTF-16, takich jak String Java, String C #, Win32 API, biblioteki Qt GUI, biblioteka Unicode ICU itp. Jednak przy tym wszystkim jest wiele podstawowych błędów w przetwarzaniu znaków poza BMP (znaki, które powinny być zakodowane przy użyciu dwóch elementów UTF-16).
Na przykład spróbuj edytować jeden z następujących znaków:
- 𝄞 ( U + 1D11E ) SYMBOL MUZYCZNY G CLEF
- 𝕥 ( U + 1D565 ) MATEMATYCZNY DOUBLE-STRUCK MAŁY T.
- 𝟶 ( U + 1D7F6 ) MATEMATYCZNA CYFRA MONOSPACE ZERO
- 𠂊 ( U + 2008A ) Han Character
Możesz przegapić niektóre, w zależności od zainstalowanych czcionek. Wszystkie te postacie znajdują się poza BMP (Basic Multilingual Plane). Jeśli nie widzisz tych znaków, możesz także spróbować spojrzeć na nie w opisie Znaków Unicode .
Na przykład spróbuj utworzyć nazwy plików w systemie Windows zawierające te znaki; spróbuj usunąć te znaki za pomocą „backspace”, aby zobaczyć, jak zachowują się w różnych aplikacjach korzystających z UTF-16. Zrobiłem kilka testów, a wyniki są dość złe:
- Opera ma problem z ich edycją (usuń wymagane 2 naciśnięcia na backspace)
- Notatnik nie radzi sobie z nimi poprawnie (usuń wymagane 2 naciśnięcia na backspace)
- Edycja nazw plików w oknach dialogowych okna w podziale (usuń wymagane 2 naciśnięcia na backspace)
- Wszystkie aplikacje QT3 nie radzą sobie z nimi - pokazują dwa puste kwadraty zamiast jednego symbolu.
- Python koduje takie znaki niepoprawnie, gdy są używane bezpośrednio
u'X'!=unicode('X','utf-16')
na niektórych platformach, gdy znak X poza BMP. - Unicodedata w Pythonie 2.5 nie uzyskuje właściwości takich znaków, gdy Python skompilowany z ciągami znaków Unicode UTF-16.
- StackOverflow wydaje się usuwać te znaki z tekstu, jeśli są edytowane bezpośrednio jako znaki Unicode (znaki te są wyświetlane za pomocą znaków ucieczki Unicode HTML).
- TextFox WinForm może generować niepoprawny ciąg znaków, gdy jest ograniczony przez MaxLength.
Wydaje się, że takie błędy są niezwykle łatwe do znalezienia w wielu aplikacjach korzystających z UTF-16.
Więc ... Czy uważasz, że UTF-16 należy uznać za szkodliwy?
Odpowiedzi:
Opinia: Tak, UTF-16 należy uznać za szkodliwy . Powodem tego jest fakt, że jakiś czas temu istniało błędne przekonanie, że widechar będzie tym, czym jest teraz UCS-4.
Pomimo „anglo-centralizmu” UTF-8 należy go uznać za jedyne przydatne kodowanie tekstu. Można argumentować, że kody źródłowe programów, stron internetowych i plików XML, nazwy plików systemu operacyjnego i inne interfejsy tekstowe między komputerami nigdy nie powinny istnieć. Ale kiedy to robią, tekst jest nie tylko dla ludzkich czytelników.
Z drugiej strony koszty ogólne UTF-8 to niewielka cena do zapłacenia, która ma znaczące zalety. Zalety, takie jak zgodność z nieświadomym kodem, który po prostu przekazuje ciągi znaków
char*
. To jest świetna rzecz. Istnieje kilka użytecznych postaci, które są SHORTER w UTF-16 niż w UTF-8.Wierzę, że wszystkie inne kodowania w końcu umrą. Wiąże się to z tym, że MS-Windows, Java, ICU, python przestają używać go jako swojego ulubionego. Po długich badaniach i dyskusjach konwencje programistyczne w mojej firmie zabraniają używania UTF-16 w dowolnym miejscu z wyjątkiem wywołań API OS, a to pomimo znaczenia wydajności w naszych aplikacjach i faktu, że używamy Windows. Funkcje konwersji zostały opracowane w celu konwersji zawsze zakładanego UTF8
std::string
na natywny UTF-16, który sam system Windows nie obsługuje poprawnie .Ludziom, którzy mówią „ używaj tego, co potrzebne, tam, gdzie jest to potrzebne ”, mówię: ogromną zaletą jest stosowanie wszędzie tego samego kodowania i nie widzę wystarczającego powodu, by robić inaczej. W szczególności myślę, że dodanie
wchar_t
do C ++ było błędem, podobnie jak dodatki Unicode do C ++ 0x. Jednak od implementacji STL należy wymagać, aby każdy parametrstd::string
lubchar*
parametr był uważany za zgodny z Unicode.Jestem także przeciwny podejściu „ używaj tego, co chcesz ”. Nie widzę powodu do takiej wolności. Występuje dość zamieszania na temat tekstu, co powoduje, że całe to zepsute oprogramowanie. Powiedziawszy powyżej, jestem przekonany, że programiści muszą wreszcie osiągnąć konsensus w sprawie UTF-8 jako jeden właściwy sposób. (Pochodzę z kraju, który nie mówi w ascii i dorastałem w systemie Windows, więc po raz ostatni oczekuje się, że zaatakuję UTF-16 z powodów religijnych).
Chciałbym udostępnić więcej informacji o tym, jak piszę tekst w systemie Windows i co polecam wszystkim innym, aby sprawdzić poprawność Unicode podczas kompilacji, łatwość użycia i lepszą wieloplatformowość kodu. Sugestia zasadniczo różni się od tego, co jest zwykle zalecane jako właściwy sposób używania Unicode w systemie Windows. Jednak dogłębne badanie tych zaleceń doprowadziło do tego samego wniosku. Więc oto idzie:
wchar_t
anistd::wstring
w żadnym innym miejscu niż przylegający punkt do interfejsów API akceptujących UTF-16._T("")
lubL""
UTF-16 literały (IMO te powinny być wyjęte z normą, jako część UTF-16 amortyzację)._UNICODE
stałą, takich jakLPTSTR
lubCreateWindow()
._UNICODE
zawsze zdefiniowane, aby uniknąć przekazywaniachar*
ciągów do WinAPI podczas cichej kompilacjistd::strings
ichar*
gdziekolwiek w programie są uważane za UTF-8 (jeśli nie podano inaczej)std::string
, chociaż możesz przekazać char * lub literał ciąg doconvert(const std::string &)
.używaj tylko funkcji Win32, które akceptują widechars (
LPWSTR
). Nigdy nie akceptująLPTSTR
lubLPSTR
. Przekaż parametry w ten sposób:(Zasady używają funkcji konwersji poniżej.)
Z ciągami MFC:
Praca z plikami, nazwami plików i fstream w systemie Windows:
std::string
lubconst char*
nazw plików dofstream
rodziny. MSVC STL nie obsługuje argumentów UTF-8, ale ma niestandardowe rozszerzenie, którego należy użyć w następujący sposób:Konwersja
std::string
argumentówstd::wstring
zUtils::Convert
:Będziemy musieli ręcznie usunąć konwersję, gdy stosunek MSVC do
fstream
zmian.fstream
przypadku 4215 dotyczącym badania / dyskusji w trybie Unicode.fopen()
z powodów RAII / OOD. W razie potrzeby użyj_wfopen()
powyższych konwencji WinAPI.źródło
Punkty kodowe Unicode nie są znakami! Czasami nie są nawet glifami (formami wizualnymi).
Kilka przykładów:
Jedynym sposobem na poprawną edycję Unicode jest użycie biblioteki napisanej przez eksperta lub zostać ekspertem i napisać własną. Jeśli tylko liczysz współrzędne, żyjesz w stanie grzechu.
źródło
Istnieje prosta ogólna zasada dotycząca tego, jakiego formularza Unicode Transformation Form (UTF) użyć: - utf-8 do przechowywania i komunikacji - utf-16 do przetwarzania danych - możesz użyć utf-32, jeśli większość używanego interfejsu API platformy to utf-32 (powszechny w świecie UNIX).
Obecnie większość systemów używa utf-16 (Windows, Mac OS, Java, .NET, ICU, Qt). Zobacz także ten dokument: http://unicode.org/notes/tn12/
Wracając do „UTF-16 jako szkodliwego”, powiedziałbym: zdecydowanie nie.
Ludzie, którzy boją się surogatów (myśląc, że przekształcają Unicode w kodowanie o zmiennej długości) nie rozumieją innych (znacznie większych) złożoności, które sprawiają, że mapowanie między znakami i punktem kodu Unicode jest bardzo złożone: łączenie znaków, ligatur, selektorów wariacji , znaki kontrolne itp.
Przeczytaj tę serię tutaj http://www.siao2.com/2009/06/29/9800913.aspx i zobacz, jak UTF-16 staje się łatwym problemem.
źródło
equalsIgnoreCase
metodzie klasy String w Javie (także inne w klasie string), który nigdy by nie istniał, gdyby Java użyła UTF-8 lub UTF-32. W każdym kodzie używającym UTF-16 są miliony tych śpiących bomb. Mam ich dość. UTF-16 to złośliwa ospa, która na zawsze plaga nasze oprogramowanie podstępnymi błędami. Jest to oczywiście szkodliwe i powinno być przestarzałe i zakazane..Substring(1)
w .NET to trywialny przykład czegoś, co psuje obsługę wszystkich Unicode innych niż BMP. Wszystko, co korzysta z UTF-16, ma ten problem; zbyt łatwo jest traktować to jako kodowanie o stałej szerokości, a problemy występują zbyt rzadko. To sprawia, że kodowanie jest aktywnie szkodliwe, jeśli chcesz obsługiwać Unicode.Tak, absolutnie.
Dlaczego? Ma to związek z ćwiczeniem kodu .
Jeśli spojrzysz na te statystyki wykorzystania współrzędnych kodowych na dużym korpusie autorstwa Toma Christiansena, zobaczysz, że trans-8-bitowe współrzędne BMP są używane o kilka rzędów, jeśli wielkość jest większa niż współrzędne non-BMP:
Weź powiedzenie TDD: „Niesprawdzony kod to uszkodzony kod” i sformatuj go jako „niewyćwiczony kod to uszkodzony kod” i zastanów się, jak często programiści mają do czynienia z punktami kodowymi innymi niż BMP.
Błędy związane z nierozpoznawaniem UTF-16 jako kodowania o zmiennej szerokości są znacznie bardziej niezauważalne niż równoważne błędy w UTF-8 . Niektóre języki programowania wciąż nie gwarantują UTF-16 zamiast UCS-2, a niektóre tak zwane języki programowania wysokiego poziomu oferują dostęp do jednostek kodowych zamiast punktów kodowych (nawet C ma zapewniać dostęp do punkty kodowe, jeśli używasz
wchar_t
, niezależnie od tego, co mogą robić niektóre platformy).źródło
Sugerowałbym, że myślenie, że UTF-16 może być uważany za szkodliwy, mówi, że musisz lepiej zrozumieć Unicode .
Poniewaz zostalam zlekcewazona za przedstawienie mojej opinii na subiektywne pytanie, pozwólcie, ze rozwinie sie. Co dokładnie przeszkadza ci w UTF-16? Wolałbyś, żeby wszystko było zakodowane w UTF-8? UTF-7? A może UCS-4? Oczywiście niektóre aplikacje nie są zaprojektowane do obsługi każdego pojedynczego kodu znaków, ale są niezbędne, szczególnie w dzisiejszej globalnej domenie informacyjnej, do komunikacji między granicami międzynarodowymi.
Ale tak naprawdę, jeśli uważasz, że UTF-16 powinien być uważany za szkodliwy, ponieważ jest mylący lub może być nieprawidłowo zaimplementowany (z pewnością może być Unicode), to jaką metodę kodowania znaków można uznać za nieszkodliwą?
EDYCJA: Wyjaśnienie: Dlaczego niewłaściwe implementacje normy odzwierciedlają jakość samej normy? Jak później zauważyli inni, fakt, że aplikacja niewłaściwie używa narzędzia, nie oznacza, że samo narzędzie jest wadliwe. Gdyby tak było, moglibyśmy prawdopodobnie powiedzieć takie słowa, jak „słowo kluczowe var uważane za szkodliwe” lub „wątki uważane za szkodliwe”. Myślę, że pytanie to myli jakość i naturę standardu z trudnościami, jakie wielu programistów ma we wdrażaniu i stosowaniu go prawidłowo, co wydaje mi się bardziej związane z ich niezrozumieniem, jak działa Unicode, niż z samym Unicode.
źródło
Nie ma nic złego w kodowaniu Utf-16. Ale języki, które traktują jednostki 16-bitowe jako znaki, należy prawdopodobnie uznać za źle zaprojektowane. Posiadanie typu o nazwie „
char
”, który nie zawsze reprezentuje postać, jest dość mylące. Ponieważ większość programistów spodziewa się, że typ znaku reprezentuje punkt kodowy lub znak, znaczna część kodu prawdopodobnie się zepsuje, gdy zostanie wystawiona na znaki poza BMP.Zauważ jednak, że nawet użycie utf-32 nie oznacza, że każdy 32-bitowy punkt kodowy zawsze będzie reprezentował znak. Ze względu na łączenie znaków rzeczywisty znak może składać się z kilku punktów kodowych. Unicode nigdy nie jest trywialny.
BTW. Prawdopodobnie istnieje ta sama klasa błędów w platformach i aplikacjach, które oczekują 8-bitowych znaków, które są zasilane Utf-8.
źródło
CodePoint
typ, zawierający pojedynczy punkt kodowy (21 bitów),CodeUnit
typ, zawierający pojedynczą jednostkę kodową (16 bitów dla UTF-16), aCharacter
typ idealnie musiałby obsługiwać kompletny grafem. Ale to sprawia, że jest to funkcjonalnie równoważne zString
...Moim osobistym wyborem jest zawsze używanie UTF-8. Jest to standard w Linuksie dla prawie wszystkiego. Jest wstecznie kompatybilny z wieloma starszymi aplikacjami. Jest bardzo minimalny narzut pod względem dodatkowej przestrzeni używanej dla znaków niełacińskich w porównaniu z innymi formatami UTF, oraz znaczna oszczędność miejsca dla znaków łacińskich. W Internecie królują języki łacińskie i myślę, że tak będzie w najbliższej przyszłości. I aby odnieść się do jednego z głównych argumentów w oryginalnym poście: prawie każdy programista jest świadomy, że UTF-8 czasami zawiera znaki wielobajtowe. Nie wszyscy radzą sobie z tym poprawnie, ale zwykle są świadomi, co jest więcej niż można powiedzieć o UTF-16. Ale oczywiście musisz wybrać najbardziej odpowiedni dla swojej aplikacji. Właśnie dlatego jest ich więcej niż jeden.
źródło
Istnieje kodowanie wykorzystujące symbole o stałym rozmiarze. Z pewnością mam na myśli UTF-32. Ale 4 bajty na każdy symbol to za dużo zmarnowanej przestrzeni, dlaczego mielibyśmy go używać w codziennych sytuacjach?
Moim zdaniem większość problemów wynika z faktu, że niektóre programy nie nadążały za standardem Unicode, ale nie szybko zaradziły tej sytuacji. Opera, Windows, Python, Qt - wszystkie pojawiły się, zanim UTF-16 stał się powszechnie znany, a nawet powstał. Mogę jednak potwierdzić, że w Operze, Eksploratorze Windows i Notatniku nie ma już problemów ze znakami spoza BMP (przynajmniej na moim komputerze). Ale w każdym razie, jeśli programy nie rozpoznają par zastępczych, to nie używają UTF-16. Jakiekolwiek problemy wynikają z radzenia sobie z takimi programami, nie mają one nic wspólnego z samym UTF-16.
Myślę jednak, że problemy ze starszym oprogramowaniem z obsługą tylko BMP są nieco przesadzone. Znaki spoza BMP występują tylko w bardzo szczególnych przypadkach i obszarach. Według oficjalnego FAQ Unicode „nawet w tekście wschodnioazjatyckim częstość występowania par zastępczych powinna wynosić średnio znacznie mniej niż 1% całej pamięci tekstowej”. Oczywiście, znaki spoza BMP nie powinny być pomijane, ponieważ w przeciwnym razie program nie jest zgodny z Unicode, ale większość programów nie jest przeznaczona do pracy z tekstami zawierającymi takie znaki. Dlatego jeśli tego nie popierają, jest to nieprzyjemne, ale nie katastroficzne.
Rozważmy teraz alternatywę. Gdyby UTF-16 nie istniał, nie mielibyśmy kodowania, które byłoby odpowiednie dla tekstu spoza ASCII, a całe oprogramowanie stworzone dla UCS-2 musiałoby zostać całkowicie przeprojektowane, aby pozostało zgodne z Unicode. Ten ostatni najprawdopodobniej spowolniłby przyjęcie Unicode. Również nie bylibyśmy w stanie utrzymać zgodności z tekstem w UCS-2, tak jak UTF-8 w stosunku do ASCII.
Odkładając na bok wszystkie starsze kwestie, jakie są argumenty przeciwko samemu kodowaniu? Naprawdę wątpię, aby programiści nie wiedzieli, że UTF-16 ma zmienną długość, jest napisany wszędzie, zaczynając od Wikipedii. UTF-16 jest znacznie trudniejszy do przeanalizowania niż UTF-8, jeśli ktoś wskazał złożoność jako możliwy problem. Błędem jest również sądzić, że łatwo jest zepsuć określenie długości łańcucha tylko w UTF-16. Jeśli używasz UTF-8 lub UTF-32, nadal powinieneś mieć świadomość, że jeden punkt kodowy Unicode niekoniecznie oznacza jeden znak. Poza tym nie sądzę, aby było coś istotnego przeciwko kodowaniu.
Dlatego nie sądzę, aby samo kodowanie było uważane za szkodliwe. UTF-16 to kompromis między prostotą a kompaktowością, a korzystanie z tego, co jest potrzebne, tam, gdzie jest to potrzebne , nie szkodzi . W niektórych przypadkach musisz pozostać kompatybilny z ASCII i potrzebujesz UTF-8, w niektórych przypadkach chcesz pracować z ideografami Hana i oszczędzać miejsce za pomocą UTF-16, w niektórych przypadkach potrzebujesz uniwersalnych reprezentacji znaków, które ustalają stałe- kodowanie długości. Użyj tego, co bardziej odpowiednie, po prostu zrób to poprawnie.
źródło
Lata internacjonalizacji systemu Windows, szczególnie w językach Azji Wschodniej, mogły mnie zepsuć, ale skłaniam się ku UTF-16 do wewnętrznych reprezentacji ciągów w programie i UTF-8 do przechowywania w sieci lub plikach dokumentów w postaci zwykłego tekstu. UTF-16 można zwykle przetwarzać szybciej w systemie Windows, więc jest to podstawowa zaleta korzystania z UTF-16 w systemie Windows.
Skok do UTF-16 znacznie poprawił adekwatność przeciętnych produktów obsługujących tekst międzynarodowy. Jest tylko kilka wąskich przypadków, w których należy wziąć pod uwagę pary zastępcze (zasadniczo usunięcia, wstawienia i łamanie linii), a przeciętny przypadek jest przeważnie prosty. I w przeciwieństwie do wcześniejszych kodowań, takich jak warianty JIS, UTF-16 ogranicza pary zastępcze do bardzo wąskiego zakresu, więc sprawdzenie jest naprawdę szybkie i działa do przodu i do tyłu.
To prawda, że jest również mniej więcej tak szybki w poprawnie zakodowanym UTF-8. Ale jest też wiele uszkodzonych aplikacji UTF-8, które niepoprawnie kodują pary zastępcze jako dwie sekwencje UTF-8. UTF-8 nie gwarantuje też zbawienia.
IE radzi sobie dość dobrze z parami zastępczymi od 2000 r., Mimo że zazwyczaj konwertuje je ze stron UTF-8 na wewnętrzną reprezentację UTF-16; Jestem całkiem pewien, że Firefox ma to również dobrze, więc tak naprawdę nie dbam o to, co robi Opera.
UTF-32 (znany również jako UCS4) jest bezcelowy dla większości aplikacji, ponieważ zajmuje tak mało miejsca, więc jest prawie niestabilny.
źródło
UTF-8 jest zdecydowanie najlepszą drogą, być może towarzyszy mu UTF-32 do użytku wewnętrznego w algorytmach wymagających wysokiej wydajności dostępu losowego (ale ignoruje łączenie znaków).
Zarówno UTF-16, jak i UTF-32 (jak również ich warianty LE / BE) cierpią na problemy związane z endianizmem, dlatego nigdy nie należy ich używać zewnętrznie.
źródło
UTF-16? zdecydowanie szkodliwe. Tylko moje ziarno soli tutaj, ale istnieją dokładnie trzy dopuszczalne kodowania tekstu w programie:
integer codepoints („CP”?): tablica największych liczb całkowitych, które są wygodne dla twojego języka programowania i platformy (rozpada się na ASCII w limicie niskich rezystancji). Powinien być int32 na starszych komputerach i int64 na cokolwiek z adresowaniem 64-bitowym.
Oczywiście interfejsy do starszego kodu używają tego, co jest potrzebne do poprawnego działania starego kodu.
źródło
U+10ffff
maksimum wyjdzie przez okno, gdy (nie jeśli) zabraknie im współrzędnych kodowych . To powiedziawszy, użycie int32 w systemie p64 dla prędkości jest prawdopodobnie bezpieczne, ponieważ wątpię, aby przekroczyły,U+ffffffff
zanim będziesz zmuszony przepisać kod dla systemów 128-bitowych około 2050 roku. jest wygodny ”w przeciwieństwie do„ największego dostępnego ”(który prawdopodobnie byłby int256 lub bignum czy coś takiego).)U+10FFFF
. To naprawdę jedna z tych sytuacji, gdy 21 bitów jest wystarczające dla każdego.Unicode definiuje punkty kodu do 0x10FFFF (1114112 kodów), wszystkie aplikacje działające w środowisku wielojęzycznym zajmującym się łańcuchami / nazwami plików itp. Powinny to poprawnie obsługiwać.
Utf-16 : obejmuje tylko 1.112.064 kodów. Chociaż te na końcu Unicode pochodzą z samolotów 15-16 (obszar prywatnego użytku). Nie może dalej rosnąć w przyszłości, z wyjątkiem złamania koncepcji Utf-16 .
Utf-8 : obejmuje teoretycznie 2 216 757 376 kodów. Aktualny zakres kodów Unicode może być reprezentowany przez maksymalnie 4 bajty. Nie ma problemu z kolejnością bajtów , jest „kompatybilny” z ascii.
Utf-32 : obejmuje teoretycznie 2 ^ 32 = 4 294 967 296 kodów. Obecnie nie jest kodowany o zmiennej długości i prawdopodobnie nie będzie w przyszłości.
Te fakty są oczywiste. Nie rozumiem zalecania ogólnego używania Utf-16 . Jest kodowany o zmiennej długości (nie jest dostępny za pomocą indeksu), ma problemy z pokryciem całego zakresu Unicode nawet w tej chwili, kolejność bajtów musi być obsługiwana itp. Nie widzę żadnej korzyści poza tym, że jest natywnie używany w systemie Windows i niektórych inne miejsca. Chociaż podczas pisania kodu na wielu platformach prawdopodobnie lepiej jest używać Utf-8 natywnie i dokonywać konwersji tylko w punktach końcowych w sposób zależny od platformy (jak już sugerowano). Gdy niezbędny jest bezpośredni dostęp do indeksu, a pamięć nie stanowi problemu, należy użyć Utf-32 .
Głównym problemem jest to, że wielu programistów zajmujących się Windows Unicode = Utf-16 nawet nie wie ani nie ignoruje faktu, że jest on zakodowany o zmiennej długości.
Sposób, w jaki zwykle jest na platformie * nix , jest całkiem niezły: łańcuchy c (char *) interpretowane jako zakodowane w Utf-8 , szerokie łańcuchy c (wchar_t *) interpretowane jako Utf-32 .
źródło
Dodaj to do listy:
Źródło: Michael S. Kaplan Blog MSDN
źródło
Niekoniecznie powiedziałbym, że UTF-16 jest szkodliwy. Nie jest elegancki, ale służy jego kompatybilności wstecznej z UCS-2, podobnie jak GB18030 robi z GB2312, a UTF-8 z ASCII.
Ale wprowadzenie fundamentalnej zmiany w strukturze Unicode w środkowej fazie, po tym jak Microsoft i Sun zbudowały ogromne interfejsy API wokół znaków 16-bitowych, było szkodliwe. Niepowodzenie w rozpowszechnianiu świadomości zmiany było bardziej szkodliwe.
źródło
UTF-16 jest najlepszym kompromisem między obsługą i przestrzenią i dlatego większość głównych platform (Win32, Java, .NET) używa go do wewnętrznej reprezentacji ciągów.
źródło
Nigdy nie zrozumiałem sensu UTF-16. Jeśli chcesz uzyskać najbardziej oszczędną przestrzennie reprezentację, użyj UTF-8. Jeśli chcesz traktować tekst jako tekst o stałej długości, użyj UTF-32. Jeśli nie chcesz, użyj UTF-16. Co gorsza, ponieważ wszystkie typowe (podstawowe płaszczyzny wielojęzyczne) znaki w UTF-16 mieszczą się w jednym punkcie kodu, błędy, które zakładają, że UTF-16 ma stałą długość, będą subtelne i trudne do znalezienia, natomiast jeśli spróbujesz to zrobić w przypadku UTF-8 Twój kod szybko i głośno zawiedzie, gdy tylko spróbujesz internacjonalizować.
źródło
Ponieważ nie mogę jeszcze komentować, zamieszczam to jako odpowiedź, ponieważ wydaje się, że inaczej nie mogę skontaktować się z autorami
utf8everywhere.org
. Szkoda, że nie dostaję automatycznie uprawnienia do komentowania, ponieważ mam wystarczającą reputację na innych zmianach stosów.Ma to stanowić komentarz do opinii: Tak, UTF-16 należy uznać za szkodliwą odpowiedź.
Jedna mała korekta:
Aby zapobiec przypadkowemu przekazaniu UTF-8
char*
do wersji ANSI-string funkcji Windows-API, należy to zdefiniowaćUNICODE
, a nie_UNICODE
._UNICODE
Funkcje Mapy podobne_tcslen
dowcslen
, nieMessageBox
doMessageBoxW
. Zamiast tegoUNICODE
definiuje to drugie. Na dowód pochodzi zWinUser.h
nagłówka MS Visual Studio 2005 :Błąd ten powinien zostać co najmniej naprawiony
utf8everywhere.org
.Sugestia:
Być może przewodnik powinien zawierać przykład jawnego użycia szerokiej struny wersji struktury danych, aby ułatwić jej pominięcie / zapomnienie. Używanie wersji struktur danych z szerokim łańcuchem oraz stosowanie wersji funkcji z szerokimi łańcuchami sprawia, że jeszcze mniej prawdopodobne jest, że przypadkowo wywoła się taką wersję funkcji w wersji ANSI.
Przykład przykładu:
źródło
_UNICODE
wciąż tam jest :(Ktoś powiedział, że UCS4 i UTF-32 były takie same. Nie, ale wiem, co masz na myśli. Jedno z nich jest jednak kodowaniem drugiego. Żałuję, że nie zastanawiali się nad określeniem endianizmu od pierwszego, aby nie toczyła się tutaj również bitwa endianess. Czy nie widzieli, że to nadchodzi? Przynajmniej UTF-8 jest wszędzie taki sam (chyba że ktoś przestrzega oryginalnej specyfikacji z 6 bajtami).
Jeśli używasz UTF-16, musisz uwzględnić obsługę znaków wielobajtowych. Nie możesz przejść do n-tego znaku, indeksując 2N w tablicy bajtów. Musisz go przejść lub mieć indeksy postaci. W przeciwnym razie napisałeś błąd.
Obecna wersja robocza specyfikacji C ++ mówi, że UTF-32 i UTF-16 mogą mieć warianty little-endian, big-endian i nieokreślone. Naprawdę? Gdyby Unicode określił, że wszyscy muszą robić little-endian od samego początku, wszystko byłoby prostsze. (Byłbym w porządku z big-endianem.) Zamiast tego, niektórzy ludzie wdrożyli to w jeden sposób, inni w inny, a teraz utknęliśmy w głupocie za nic. Czasami zawód inżyniera oprogramowania jest krępujący.
źródło
Nie uważam, że to szkodliwe, jeśli deweloper jest wystarczająco ostrożny.
I powinni zaakceptować tę kompromis, jeśli też dobrze wiedzą.
Jako japoński programista uważam, że UCS-2 jest wystarczająco duży, a ograniczenie przestrzeni najwyraźniej upraszcza logikę i zmniejsza pamięć środowiska wykonawczego, więc używanie utf-16 w ramach ograniczeń UCS-2 jest wystarczająco dobre.
Istnieje system plików lub inna aplikacja, która zakłada, że punkty kodowe i bajty są proporcjonalne, dzięki czemu można zagwarantować, że nieprzetworzona liczba punktów kodowych będzie pasować do pamięci o ustalonym rozmiarze.
Jednym z przykładów jest NTFS i VFAT określające UCS-2 jako kodowanie pamięci plików.
Jeśli ten przykład naprawdę chce rozszerzyć się o obsługę UCS-4, i tak mógłbym zgodzić się na użycie utf-8 do wszystkiego, ale stała długość ma takie zalety, jak:
W przyszłości, gdy moc pamięci / przetwarzania będzie tania, nawet w jakichkolwiek urządzeniach wbudowanych, możemy zaakceptować, że urządzenie jest nieco wolne z powodu dodatkowych błędów pamięci podręcznej lub błędów stron i dodatkowego użycia pamięci, ale chyba nie nastąpi to w najbliższej przyszłości ...
źródło
Całkiem możliwe, ale alternatywy niekoniecznie powinny być postrzegane jako znacznie lepsze.
Podstawową kwestią jest to, że istnieje wiele różnych koncepcji na temat: glifów, znaków, punktów kodowych i sekwencji bajtów. Odwzorowanie między nimi jest nietrywialne, nawet przy pomocy biblioteki normalizacyjnej. (Na przykład niektóre znaki w językach europejskich, które są napisane skryptem łacińskim, nie są pisane pojedynczym kodem Unicode. I to jest na prostszym końcu złożoności!) Oznacza to, że uzyskanie poprawności jest dość zadziwiające trudny; dziwnych błędów należy się spodziewać (i zamiast po prostu narzekać na ich temat, powiedz opiekunom danego oprogramowania).
Jedynym sposobem, w jaki UTF-16 może być uważany za szkodliwy w przeciwieństwie do, powiedzmy, UTF-8, jest inny sposób kodowania punktów kodowych poza BMP (jako para surogatów). Jeśli kod chce uzyskać dostęp lub iterować według kodu, oznacza to, że musi być świadomy różnicy. OTOH, oznacza to, że znaczna część istniejącego kodu, który zakłada „znaki”, zawsze może być dopasowana do dwubajtowej liczby - dość powszechne, jeśli błędne założenie - może przynajmniej kontynuować pracę bez odbudowywania wszystkiego. Innymi słowy, przynajmniej zobaczysz te postacie, które nie są odpowiednio traktowane!
Odwróciłbym twoje pytanie do głowy i powiedziałbym, że cały ten przeklęty Unicode powinien być uważany za szkodliwy i każdy powinien używać kodowania 8-bitowego, z wyjątkiem tego, co widziałem (w ciągu ostatnich 20 lat), gdzie to prowadzi: okropne zamieszanie związane z różnymi kodowaniami ISO 8859, a także z całym zestawem kodowań używanych w cyrylicy i pakietem EBCDIC oraz… no cóż, Unicode dla wszystkich jego błędów pokonuje to. Gdyby to nie był tak paskudny kompromis między nieporozumieniami różnych krajów.
źródło