Odpowiedź
To jest stara odpowiedź.
Zobacz UTF-8 Everywhere , aby uzyskać najnowsze aktualizacje.
Opinia: Tak, UTF-16 należy uznać za szkodliwe . Powodem tego jest to, że jakiś czas temu istniało błędne przekonanie, że widechar będzie tym, czym teraz jest UCS-4.
Pomimo „anglocentryzmu” UTF-8, należy traktować jako jedyne przydatne kodowanie tekstu. Można argumentować, że kody źródłowe programów, stron internetowych i plików XML, nazw plików systemu operacyjnego i innych tekstowych interfejsów komputer-komputer 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, choć ma znaczące zalety. Zalety, takie jak zgodność z nieświadomym kodem, który po prostu przekazuje ciągi z char*
. To wspaniała rzecz. Jest kilka użytecznych znaków, które są KRÓTSZE w UTF-16 niż w UTF-8.
Uważam, że wszystkie inne kodowania w końcu umrą. Wiąże się to z tym, że MS-Windows, Java, ICU, python przestań używać go jako ulubionego. Po długich badaniach i dyskusjach, konwencje programistyczne w mojej firmie zakazują używania UTF-16 w dowolnym miejscu z wyjątkiem wywołań OS API, i to pomimo znaczenia wydajności w naszych aplikacjach i fakt, że używamy systemu Windows. Funkcje konwersji zostały opracowane w celu konwersji zawsze zakładanego-UTF8 std::string
do natywnego UTF-16, który sam Windows nie obsługuje poprawnie .
Osobom, które mówią „ używaj tego, co jest potrzebne, tam, gdzie jest to potrzebne”, mówię: „korzystanie z tego samego kodowania wszędzie ma ogromną przewagę i nie widzę wystarczającego powodu, aby W szczególności uważam, że dodanie wchar_t
do C ++ było błędem, podobnie jak dodatki Unicode do C ++ 0x. Jednak implementacje STL muszą wymagać, aby każdy Parametr std::string
lub char*
byłby uważany za zgodny z Unicode.
Jestem również przeciwny „ użyciu co chcesz „. Nie widzę powodu do takiej wolności. Wystarczająco dużo zamieszania w temacie tekstu, co powoduje całe to zepsute oprogramowanie. Powiedziawszy powyżej, jestem przekonany, że programiści muszą wreszcie dojść do konsensusu w sprawie UTF-8 jako jednej właściwej drogi. (Pochodzę z kraju, w którym nie mówi się językiem ascii i dorastałem w systemie Windows, więc ostatnio oczekuje się ode mnie ataku na UTF-16 z powodów religijnych).
Chciałbym podzielić się więcej informacjami o tym, jak robię tekst w systemie Windows i co polecam wszystkim innym za sprawdzoną w czasie kompilacji poprawność Unicode, łatwość użycia i lepszą wieloplatformowość kodu. Sugestia znacznie 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. A więc tutaj:
- Nie używaj
wchar_t
ani std::wstring
w żadnym innym miejscu niż przyległy do Interfejsy API akceptujące UTF-16.
- Nie używaj
_T("")
ani L""
literałów UTF-16 (powinny być wyjęte ze standardu IMO , jako część wycofania UTF-16).
- Nie używaj typów, funkcji ani ich pochodnych wrażliwych na stałą
_UNICODE
, na przykład LPTSTR
lub CreateWindow()
.
- Jednak
_UNICODE
zawsze zdefiniowane, aby unikaj przekazywania ciągów char*
do WinAPI podczas cichej kompilacji
-
std::strings
i char*
gdziekolwiek w programie są traktowane jako UTF-8 (jeśli nie podano inaczej)
- Wszystkie moje ciągi są
std::string
, chociaż możesz przekazać znak * lub literał ciągu do convert(const std::string &)
.
-
Używaj tylko funkcji Win32, które akceptują widechars (LPWSTR
). Nigdy te, które akceptują LPTSTR
lub LPSTR
. Przekaż parametry w ten sposób:
::SetWindowTextW(Utils::convert(someStdString or "string litteral").c_str())
(Zasady używają poniższych funkcji konwersji).
-
Z ciągami MFC :
CString someoneElse; // something that arrived from MFC. Converted as soon as possible, before passing any further away from the API call: std::string s = str(boost::format("Hello %s\n") % Convert(someoneElse)); AfxMessageBox(MfcUtils::Convert(s), _T("Error"), MB_OK);
-
Praca z plikami, nazwami plików i fstream w systemie Windows:
- Nigdy nie przechodź
std::string
lub const char*
argumenty nazwy pliku dla fstream
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:
-
Konwertuj std::string
argumenty na std::wstring
with Utils::Convert
:
std::ifstream ifs(Utils::Convert("hello"), std::ios_base::in | std::ios_base::binary);
Będziemy musieli ręcznie usunąć konwersję, gdy stosunek MSVC do fstream
zmieni się.
- Ten kod nie jest wieloplatformowy i może wymagać ręcznej zmiany w przyszłość
- Zobacz
fstream
badanie Unicode / przypadek dyskusyjny 4215, aby uzyskać więcej informacji.
- Nigdy nie twórz tekstowych plików wyjściowych z zawartością inną niż UTF8
- Unikaj używania
fopen()
z powodów RAII / OOD. W razie potrzeby użyj konwencji _wfopen()
i WinAPI powyżej.
// For interface to win32 API functions std::string convert(const std::wstring& str, unsigned int codePage /*= CP_UTF8*/) { // Ask me for implementation.. ... } std::wstring convert(const std::string& str, unsigned int codePage /*= CP_UTF8*/) { // Ask me for implementation.. ... } // Interface to MFC std::string convert(const CString &mfcString) { #ifdef UNICODE return Utils::convert(std::wstring(mfcString.GetString())); #else return mfcString.GetString(); // This branch is deprecated. #endif } CString convert(const std::string &s) { #ifdef UNICODE return CString(Utils::convert(s).c_str()); #else Exceptions::Assert(false, "Unicode policy violation. See W569"); // This branch is deprecated as it does not support unicode return s.c_str(); #endif }
Komentarze
Odpowiedź
Punkty kodowe Unicode nie są znakami! Czasami nie są to nawet glify (formy wizualne) .
Kilka przykładów:
- rzymskie znaki kodowe, takie jak „ⅲ”. (Pojedynczy znak, który wygląda jak „iii”.)
- Znaki akcentowane, takie jak „á”, które mogą być reprezentowane albo jako pojedynczy złożony znak „\ u00e1”, albo jako znak i oddzielone znaki diakrytyczne „\ u0061 \ u0301 ”.
- Znaki takie jak grecka mała litera sigma, które mają różne formy na środku („ σ ”) i końcu („ ς ”) pozycji wyrazów, ale które należy traktować jako synonimy wyszukiwania.
- Dowolny łącznik Unicode U + 00AD, który może być wyświetlany wizualnie lub nie, w zależności od kontekstu i który jest ignorowany w wyszukiwaniu semantycznym.
Jedyne sposoby uzyskania edycji Unicode dobrze jest skorzystać z biblioteki napisanej przez eksperta lub zostać ekspertem i napisać własną. Jeśli liczysz tylko punkty kodowe, żyjesz w stanie grzechu.
Komentarze
Odpowiedź
Istnieje prosta praktyczna zasada dotycząca tego, jakiego formatu transformacji Unicode (UTF) należy używać: – utf-8 do przechowywania i komunikacji – utf-16 do przetwarzania danych – możesz przejść z utf-32, jeśli większość używanego interfejsu API platformy to utf-32 (powszechne w świecie UNIX).
Większość dzisiejszych systemów używa utf-16 (Windows, Mac OS, Java, .NET, ICU , Qt). Zobacz także ten dokument: http://unicode.org/notes/tn12/
Powrót do „UTF-16 jako szkodliwy”, 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) zawiłości, które powodują odwzorowanie między znakami a bardzo złożony punkt kodowy Unicode: łączenie znaków, ligatur, selektorów wariacji, znaków sterujących itp.
Po prostu przeczytaj tę serię tutaj http://www.siao2.com/2009/06/29/9800913.aspx i zobacz, jak UTF-16 staje się łatwym problemem.
Komentarze
Odpowiedź
Tak, absolutnie.
Dlaczego? Ma to związek z ćwiczeniem kodu .
Jeśli spojrzysz na te statystyki użycia punktów kodowych w dużym korpusie Tom Christiansen, „zobaczysz, że trans-8-bitowe punkty kodu BMP są używane kilka rzędów, jeśli wielkość jest większa niż punkty kodowe inne niż BMP:
2663710 U+002013 ‹–› GC=Pd EN DASH 1065594 U+0000A0 ‹ › GC=Zs NO-BREAK SPACE 1009762 U+0000B1 ‹±› GC=Sm PLUS-MINUS SIGN 784139 U+002212 ‹−› GC=Sm MINUS SIGN 602377 U+002003 ‹ › GC=Zs EM SPACE 544 U+01D49E ‹𝒞› GC=Lu MATHEMATICAL SCRIPT CAPITAL C 450 U+01D4AF ‹𝒯› GC=Lu MATHEMATICAL SCRIPT CAPITAL T 385 U+01D4AE ‹𝒮› GC=Lu MATHEMATICAL SCRIPT CAPITAL S 292 U+01D49F ‹𝒟› GC=Lu MATHEMATICAL SCRIPT CAPITAL D 285 U+01D4B3 ‹𝒳› GC=Lu MATHEMATICAL SCRIPT CAPITAL X
Weź powiedzenie TDD: „Niesprawdzony kod to uszkodzony kod” i przeformułuj go jako „niewykorzystany kod to uszkodzony kod” i zastanów się, jak często programiści mają do czynienia z punktami kodowymi spoza BMP.
Błędy związane z brakiem obsługi UTF-16 jako kodowania o zmiennej szerokości są dużo bardziej prawdopodobne, że pozostaną niezauważone niż odpowiadające im błędy w UTF-8 . Niektóre języki programowania nadal nie gwarantuj, że dostaniesz UTF-16 zamiast UCS-2, a niektóre tak zwane języki programowania wysokiego poziomu oferują dostęp do jednostek kodu zamiast punktów kodowych (nawet C ma zapewniać dostęp do punktów kodowych, jeśli używasz wchar_t
, niezależnie od tego, co jakiś plat mogą to zrobić).
Komentarze
Odpowiedź
Sugerowałbym, że myślenie, że UTF-16 można uznać za szkodliwe, mówi, że musisz lepiej zrozumieć Unicode .
Ponieważ zostałem odrzucony za przedstawienie mojej opinii na temat subiektywnego pytania, pozwól mi rozwinąć. Co dokładnie przeszkadza ci w UTF-16? Czy wolałbyś, żeby wszystko było zakodowane w UTF-8? UTF-7? Albo A co z UCS-4? Oczywiście, niektóre aplikacje nie są zaprojektowane do obsługi każdego kodu pojedynczego znaku, ale są one niezbędne, zwłaszcza 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 to być Unicode), to jaka metoda kodowania znaków byłaby uważana za nieszkodliwą?
EDYTUJ: Wyjaśnienie: dlaczego niewłaściwe wdrożenie standardu jest odzwierciedleniem jakości samego standardu? Jak później zauważyli inni, sam fakt, że aplikacja używa narzędzia w niewłaściwy sposób, nie oznacza, że narzędzie sam w sobie jest wadliwy. Gdyby tak było, moglibyśmy prawdopodobnie powiedzieć takie rzeczy, jak „słowo kluczowe var uważane za szkodliwe” lub „wątki uznane za szkodliwe”. Myślę, że pytanie to myli jakość i charakter standardu z trudnościami, jakie wielu programistów ma we wdrażaniu i używanie go właściwie, co moim zdaniem wynika bardziej z braku zrozumienia, jak działa Unicode, a nie z samego Unicode.
Komentarze
Odpowiedź
Nie ma nic złego w Utf- 16 kodowania. Ale języki, które traktują jednostki 16-bitowe jako znaki, należy prawdopodobnie uznać za źle zaprojektowane. Typ o nazwie „char
”, który nie zawsze reprezentuje znak, jest dość mylący. Ponieważ większość programistów oczekuje, że typ char reprezentuje punkt kodowy lub znak, większość kodu prawdopodobnie ulegnie uszkodzeniu, gdy zostanie wystawiony na znaki poza BMP.
Należy jednak pamiętać, ż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.
Przy okazji. Prawdopodobnie istnieje ta sama klasa błędów związanych z platformami i aplikacjami, które oczekują znaków 8-bitowych, które są zasilane Utf-8.
Komentarze
Odpowiedź
Mój osobisty wybór to zawsze używać UTF-8. To standard w Linuksie dla prawie wszystkiego. Jest wstecznie kompatybilny z wieloma starszymi aplikacjami. Istnieje bardzo minimalny narzut pod względem dodatkowej przestrzeni używanej dla znaków innych niż łacińskie w porównaniu z innymi formatami UTF, a także istnieje znaczna oszczędność miejsca na znaki łacińskie. W Internecie dominują języki łacińskie i myślę, że tak będzie w najbliższej przyszłości. I żeby odnieść się do jednego z głównych argumentów w oryginalnym poście: prawie każdy programista jest świadomy, że UTF-8 będzie czasami zawierał znaki wielobajtowe. Nie wszyscy radzą sobie z tym poprawnie, ale zwykle są tego świadomi, co jest więcej niż można powiedzieć o UTF-16. Ale oczywiście musisz wybrać najbardziej odpowiedni dla swojej aplikacji. Dlatego właśnie „na pierwszym miejscu” jest więcej niż jeden.
Komentarze
Odpowiedź
Cóż, 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 zbyt dużo zmarnowanego miejsca, dlaczego mielibyśmy go używać w codziennych sytuacjach?
Moim zdaniem większość problemów wynika z faktu, że niektóre oprogramowanie uległo awarii za standardem Unicode, ale nie udało się szybko naprawić sytuacji. Opera, Windows, Python, Qt – wszystkie pojawiły się zanim UTF-16 stał się powszechnie znany lub nawet zaistniał. Mogę jednak potwierdzić, że w Operze, Eksploratorze Windows i Notatniku nie ma już problemów ze znakami spoza BMP (przynajmniej na moim komputerze). Ale tak czy inaczej, jeśli programy nie rozpoznają par zastępczych, to nie używają UTF-16. Jakiekolwiek problemy wynikną z obsługi takich programów, nie mają one nic wspólnego z samym UTF-16.
Uważam jednak, że problemy starszego oprogramowania z obsługą tylko BMP są nieco przesadzone. Znaki spoza BMP spotyka się tylko w bardzo specyficznych przypadkach i obszarach. Zgodnie z oficjalnymi często zadawanymi pytaniami dotyczącymi Unicode , „nawet w tekstach wschodnioazjatyckich częstość występowania par zastępczych powinna wynosić średnio znacznie mniej niż 1% całego przechowywania tekstu”.Oczywiście znaków spoza BMP nie należy lekceważyć , ponieważ w innym przypadku program nie jest zgodny z Unicode, ale większość programów nie jest przeznaczona do pracy z tekstami zawierającymi takie znaki. poprzyj to, jest to nieprzyjemne, ale nie katastrofa.
Rozważmy teraz alternatywę. Gdyby UTF-16 nie istniał, to nie mielibyśmy kodowania, które byłoby dobrze dostosowane do tekstu innego niż ASCII, a całe oprogramowanie stworzone dla UCS-2 musiałoby zostać całkowicie przeprojektowane, aby zachować zgodność z Unicode. Ten ostatni najprawdopodobniej tylko spowolniłby adopcję Unicode. Nie bylibyśmy również w stanie zachować kompatybilności z tekstem w UCS-2, tak jak w przypadku UTF-8 w odniesieniu do ASCII.
Pomijając wszystkie dotychczasowe problemy, jakie są argumenty przeciwko kodowaniu Naprawdę wątpię, czy współcześni programiści nie wiedzą, że UTF-16 jest zmienną długością, jest napisany wszędzie, gdzie jest Wikipedia. UTF-16 jest znacznie mniej trudny do przeanalizowania niż UTF-8, jeśli ktoś wskazał złożoność jako możliwy problem. Błędem jest również myślenie, że łatwo jest zepsuć określanie długości łańcucha tylko w UTF-16. Jeśli używasz UTF-8 lub UTF-32, nadal powinieneś być świadomy, że jeden punkt kodu Unicode niekoniecznie oznacza jeden znak. Poza tym nie sądzę, aby było coś istotnego przeciwko kodowaniu.
Dlatego uważam, że samo kodowanie nie powinno być uważane za szkodliwe. UTF-16 to kompromis między prostotą a zwartością. Nie ma nic złego w używaniu tego, co jest potrzebne tam, gdzie jest to potrzebne . W niektórych przypadkach musisz zachować zgodność z ASCII i potrzebujesz UTF-8, w niektórych przypadkach chcesz pracować z ideogramami Han i oszczędzać miejsce przy użyciu UTF-16, w niektórych przypadkach potrzebujesz uniwersalnych reprezentacji znaków, używając -kodowanie długości. Użyj tego, co jest bardziej odpowiednie, po prostu zrób to poprawnie.
Komentarze
Odpowiedź
Lata pracy nad internacjonalizacją systemu Windows, zwłaszcza w językach wschodnioazjatyckich, mogły mnie zepsuć, ale skłaniam się ku UTF-16 do reprezentacji ciągów wewnątrz programu i UTF-8 do przechowywania w sieci lub plików zwykłego tekstu. jak dokumenty. UTF-16 można zwykle przetwarzać szybciej w systemie Windows, więc jest to główna zaleta korzystania z UTF-16 w systemie Windows.
Przejście na UTF-16 radykalnie poprawiło adekwatność obsługi przeciętnych produktów tekst międzynarodowy.Istnieje tylko kilka wąskich przypadków, w których należy wziąć pod uwagę pary zastępcze (w zasadzie delecje, wstawienia i łamanie linii), a przypadek średni to przeważnie proste przejście. W przeciwieństwie do wcześniejszych kodowań, takich jak warianty JIS, UTF-16 ogranicza pary zastępcze do bardzo wąskiego zakresu, więc sprawdzanie jest naprawdę szybkie i działa do przodu i do tyłu.
To prawda, jest mniej więcej tak samo szybkie w przypadku prawidłowego- zakodował również UTF-8. Ale jest też wiele zepsutych aplikacji UTF-8, które niepoprawnie kodują pary zastępcze jako dwie sekwencje UTF-8. Tak więc UTF-8 też nie gwarantuje zbawienia.
IE radzi sobie z parami zastępczymi dość dobrze od 2000 roku, chociaż zazwyczaj konwertuje je ze stron UTF-8 na wewnętrzną reprezentację UTF-16; „Jestem prawie pewien, że Firefox też ma rację, więc nie obchodzi mnie, co robi Opera.
UTF-32 (aka UCS4) nie ma sensu dla większości aplikacji, ponieważ zajmuje dużo miejsca, więc to raczej nie start.
Komentarze
Odpowiedź
UTF-8 to zdecydowanie najlepsza droga, której prawdopodobnie towarzyszy UTF-32 do użytku wewnętrznego używać w algorytmach, które wymagają wysokiej wydajności losowego dostępu (ale ignoruje łączenie znaków).
Zarówno UTF-16, jak i UTF-32 (a także ich warianty LE / BE) mają problemy z endianess, więc powinny nigdy nie mogą być używane zewnętrznie.
Komentarze
Odpowiedź
UTF-16? zdecydowanie szkodliwe. Moje ziarno soli tutaj, ale istnieją dokładnie trzy dopuszczalne kodowania tekstu w programie:
- ASCII: w przypadku rzeczy niskiego poziomu (np .: mikrokontrolerów), których nie stać na nic lepszego
- UTF8: przechowywanie na nośnikach o stałej szerokości, takich jak pliki
-
integer codepoints („CP”?): tablica największych liczb całkowitych, które są wygodne dla twojego języka programowania i platformę (rozpada się do ASCII w granicach niskich rezystancji). Powinien być int32 na starszych komputerach i int64 na wszystkim z 64-bitowym adresowaniem.
-
Oczywiście interfejsy do użycia starszego kodu jakie kodowanie jest potrzebne, aby stary kod działał poprawnie.
Komentarze
Odpowiedź
Unicode definiuje punkty kodowe do 0x10FFFF (1 114 112 kodów), wszystkie aplikacje działają w wielojęzycznym środowisku z ciągami znaków / nazwami plików itp. powinny obsługiwać to poprawnie.
Utf-16 : obejmuje tylko 1112 064 kody. Chociaż te na końcu Unicode pochodzą z samolotów 15-16 (obszar użytku prywatnego). Nie może się dalej rozwijać w przyszłości, z wyjątkiem złamania koncepcji Utf-16 .
Utf-8 : obejmuje teoretycznie 2216,757,376 kodów. Bieżący zakres kodów Unicode może być reprezentowany przez maksymalnie 4-bajtową sekwencję. 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, jak zalecać ogólne używanie Utf-16 . Jest zakodowany o zmiennej długości (nie można uzyskać do niego dostępu za pomocą indeksu), ma problemy z pokryciem całego zakresu Unicode nawet obecnie, 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 innych miejscach. Nawet jeśli pisząc kod wieloplatformowy, prawdopodobnie lepiej jest używać natywnie Utf-8 i dokonywać konwersji tylko w punktach końcowych w sposób zależny od platformy (jak już sugerowano). Gdy konieczny jest bezpośredni dostęp przez indeks, 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 lub ignoruje fakt, że jest zakodowany o zmiennej długości.
Sposób, w jaki zwykle jest na platformie * nix , jest całkiem niezły, ciągi c (char *) interpretowane jako Utf-8 zakodowane, szerokie ciągi c (wchar_t *) interpretowane jako Utf-32 .
Komentarze
Odpowiedź
Dodaj to do listy:
Przedstawiony scenariusz jest prosty (jeszcze prostszy, ponieważ przedstawię go tutaj niż pierwotnie! ): 1. Pole tekstowe WinForms znajduje się na formularzu, puste. Ma MaxLength ustawioną na 20 .
2.Użytkownik pisze do TextBox, a może wkleja do niego tekst.
3. Bez względu na to, co wpiszesz lub wkleisz do TextBox, jesteś ograniczony do 20, chociaż będzie sympatycznie sygnalizować tekst poza 20 (tutaj YMMV; Zmieniłem mój schemat dźwiękowy aby uzyskać taki efekt!).
4.Niewielka paczka tekstu jest następnie wysyłana w inne miejsce, aby rozpocząć ekscytującą przygodę.
To łatwy scenariusz i każdy może to napisać w wolnym czasie. Po prostu napisałem to sam w wielu językach programowania przy użyciu WinForms, ponieważ byłem znudzony i nigdy wcześniej tego nie próbowałem. I z tekstem w wielu językach, ponieważ jestem podłączony w ten sposób i mam więcej układów klawiatury niż ktokolwiek w całym pieprzonym wszechświecie.
Nawet nazwałem formularz Magic Carpet Ride , aby pomóc złagodzić nudę.
To nie zadziałało, bez względu na to, ile jest warte.
Zamiast tego wprowadziłem następujące 20 znaków w moim Magic Carpet Ride formularz:
0123401234012340123 𠀀
Ups.
Ten ostatni znak to U + 20000, pierwszy Ideogram rozszerzenia B Unicode (aka U + d840 U + dc00, do jego bliskich przyjaciół, przed którymi nie wstydzi się rozebrać) ….
A teraz mamy grę w piłkę.
Ponieważ TextBox. MaxLength mówi o
Pobiera lub ustawia maksymalną liczbę znaków, które można ręcznie wprowadzić w polu tekstowym.
tak naprawdę oznacza to
Pobiera lub ustawia maksymalna liczba kodów UTF-16 LE Jednostki, które można ręcznie wprowadzić do pola tekstowego i bezlitośnie wycinają żywe bzdury z każdego ciągu, który próbuje grać w słodkie gry z językowym pojęciem postaci, że tylko ktoś tak obsesyjny jak ten Kaplan uzna za obraźliwy (Jezu, musi wyjdź więcej!).
Spróbuję zaktualizować dokument ….
Stali czytelnicy, pamiętaj, że moje serie UCS-2 do UTF-16 zauważą moje niezadowolenie z uproszczonego pojęcia TextBox.MaxLength i jak powinien obsłużyć przynajmniej ten przypadek, w którym jego drakońskie zachowanie tworzy niedozwoloną sekwencję, taką, którą inne części .Net Framework mogą generować
- System.Text.EncoderFallbackException : Nie można przetłumaczyć znaku Unicode \ uD850 w indeksie 0 na określoną stronę kodową. *
Wyjątek, jeśli przekażesz ten ciąg w innym miejscu w .Net Framework (tak jak robił to mój kolega Dan Thompson).
W porządku, być może cała seria UCS-2 do UTF-16 jest poza zasięgiem wielu osób.
Ale nie jest „Czy rozsądnie jest oczekiwać, że TextBox.Text nie wygeneruje System.String , który nie spowoduje, że„ nie spowoduje wyrzucenia innego elementu .Net Framework? Chodzi mi o to, że nie jest tak, że istnieje szansa w postaci jakiegoś zdarzenia na kontrolce, która informuje Cię o zbliżającym się obcięciu, w którym można łatwo dodać inteligentniejszą walidację – walidację, której sama kontrolka nie ma nic przeciwko. posunąć się nawet do stwierdzenia, że ta punkowa kontrola łamie umowę dotyczącą bezpieczeństwa, która może nawet prowadzić do problemów z bezpieczeństwem, jeśli można zaklasyfikować powodujące nieoczekiwane wyjątki do zakończenia aplikacji jako prymitywny rodzaj odmowy usługi. algorytm lub technika dają nieprawidłowe wyniki?
Źródło: Michael S.Blog Kaplan MSDN
Komentarze
Odpowiedź
Niekoniecznie bym powiedział, że UTF-16 jest szkodliwy. Nie jest elegancki, ale służy swojej kompatybilności wstecznej z UCS-2, tak jak GB18030 robi z GB2312, a UTF-8 robi z ASCII.
Jednak dokonanie fundamentalnej zmiany w strukturze Unicode w midstream, po tym, jak Microsoft i Sun zbudowały ogromne API wokół znaków 16-bitowych, było szkodliwe. Niepowodzenie w rozpowszechnianiu świadomości zmiany było bardziej szkodliwe.
Komentarze
Odpowiedź
Odpowiedź
Nigdy nie rozumiałem, o co chodzi w UTF-16. Jeśli chcesz uzyskać najbardziej efektywną przestrzennie reprezentację, użyj UTF-8. Jeśli chcesz mieć możliwość traktuj 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 (podstawowa wielojęzyczna płaszczyzna) znaki w UTF-16 mieszczą się w jednym punkcie kodowym, błędy zakładające że UTF-16 ma stałą długość będzie subtelny i trudny do znalezienia, podczas gdy jeśli spróbujesz to zrobić z UTF-8, twój kod zawiedzie szybko i głośno, gdy tylko spróbujesz umiędzynarodowić.
Odpowiedź
Ponieważ nie mogę jeszcze komentować, zamieszczam to jako odpowiedź, ponieważ wygląda na to, że nie mogę inaczej skontaktować się z autorami . Szkoda, że nie otrzymuję automatycznie uprawnień do komentowania, ponieważ mam wystarczającą reputację na innych giełdach stosów.
To jest komentarz do opinii: tak, UTF-16 należy uznać za szkodliwy odpowiedź.
Jedna mała poprawka:
Aby zapobiec przypadkowemu przekazaniu kodu UTF-8 char*
do ciągowych wersji ANSI funkcji Windows-API, należy zdefiniuj UNICODE
, a nie _UNICODE
. _UNICODE
mapuje funkcje, takie jak _tcslen
, na wcslen
, a nie MessageBox
do MessageBoxW
. Zamiast tego UNICODE
definicja zajmie się tym drugim. Na dowód pochodzi to z nagłówka WinUser.h
MS Visual Studio 2005:
#ifdef UNICODE #define MessageBox MessageBoxW #else #define MessageBox MessageBoxA #endif // !UNICODE
Co najmniej ten błąd powinien zostać poprawiony na utf8everywhere.org
.
Sugestia:
Być może przewodnik powinien zawierać przykład jawnego użycia metody Wide- tekstowa wersja struktury danych, aby łatwiej było ją przeoczyć / zapomnieć.Korzystanie z wersji struktur danych z szerokimi ciągami znaków oprócz korzystania z wersji funkcji z szerokimi ciągami sprawia, że jest jeszcze mniej prawdopodobne, że ktoś przypadkowo wywoła wersję ciągów ANSI takiej funkcji.
Przykład:
WIN32_FIND_DATAW data; // Note the W at the end. HANDLE hSearch = FindFirstFileW(widen("*.txt").c_str(), &data); if (hSearch != INVALID_HANDLE_VALUE) { FindClose(hSearch); MessageBoxW(nullptr, data.cFileName, nullptr, MB_OK); }
Komentarze
Odpowiedź
Ktoś powiedział, że UCS4 i UTF-32 były To samo. Nie, ale wiem, co masz na myśli. Jeden z nich jest kodowaniem drugiego. Chciałbym, żeby pomyśleli o określeniu endianness od pierwszego, więc nie toczylibyśmy tutaj bitwy endianess. Czy nie widzieli, że to nadchodzi? Przynajmniej UTF-8 jest zawsze taki sam re (chyba że ktoś przestrzega oryginalnej specyfikacji 6-bajtowej).
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 znaków. 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 również w porządku z big-endianem.) Zamiast tego niektórzy ludzie zaimplementowali to w jeden sposób, inni w inny, a teraz „tkwimy w głupocie za nic. Czasami bycie inżynierem oprogramowania jest krępujące.
Komentarze
Odpowiedź
Nie sądzę, by było to szkodliwe, jeśli programista jest wystarczająco ostrożny.
Powinni zaakceptować ten kompromis, jeśli też dobrze wiedzą.
Jako japoński programista uważam, że UCS-2 jest wystarczająco duży i ograniczenie miejsca najwyraźniej upraszcza logikę i zmniejsza ilość pamięci uruchomieniowej, więc użycie utf-16 pod ograniczeniami 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 nieprzetworzony numer punktu kodowego będzie pasował do jakiejś pamięci o stałym rozmiarze.
Jednym z przykładów jest NTFS i VFAT z podaniem UCS-2 jako kodowania nazwy pliku.
Jeśli ten przykład naprawdę chce rozszerzyć obsługę UCS-4, i tak mógłbym zgodzić się na użycie utf-8 do wszystkiego, ale stała długość ma dobre strony, takie jak:
- może gwarantuje, że rozmiar według długości (rozmiar danych i długość punktu kodowego są proporcjonalne)
- może używać numeru kodowania do wyszukiwania skrótów
- nieskompresowane dane mają rozsądny rozmiar (w porównaniu do utf-32 / UCS-4)
W przyszłości, gdy pamięć / moc obliczeniowa będzie tania, nawet w jakimkolwiek urządzeniu wbudowanym, możemy zaakceptować, że urządzenie będzie nieco powolne ze względu na dodatkowe błędy w pamięci podręcznej lub błędy stron i dodatkową pamięć użycia, ale myślę, że nie nastąpi to w najbliższej przyszłości …
Komentarze
Odpowiedź
„Powinien być jednym z najpopularniejszych kodowania UTF-16 należy uznać za szkodliwe? „
Całkiem możliwe, ale alternatywy niekoniecznie powinny być postrzegane jako znacznie lepsze.
Podstawową kwestią jest to, że istnieje wiele różnych koncepcji dotyczących: glifów, znaków, punktów kodowych i sekwencji bajtów. Odwzorowanie pomiędzy każdym z nich jest nietrywialne, nawet przy pomocy biblioteki normalizacji. (Na przykład niektóre znaki w językach europejskich, które są zapisywane w alfabecie łacińskim, nie są pisane za pomocą jednego punktu kodowego Unicode. I to jest prostszy koniec złożoności!) Oznacza to, że aby wszystko było poprawne, dość zdumiewająco trudne; można się spodziewać dziwacznych błędów (i zamiast narzekać na nie tutaj, powiedz opiekunom danego oprogramowania).
Jedyny sposób, w jaki UTF- 16 można uznać za szkodliwą w przeciwieństwie do, powiedzmy, UTF-8, ponieważ ma inny sposób kodowania punktów kodowych poza BMP (jako para zastępców). Jeśli kod chce uzyskać dostęp lub iterować po punkcie kodowym, oznacza to, że musi zdawać sobie sprawę z różnicy. OTOH, oznacza to, że znaczna część istniejącego kodu, który zakłada „znaki”, może zawsze zmieścić się w wielkości dwubajtowej – dość powszechne, jeśli błędne założenie – przynajmniej kontynuuj pracę bez przebudowywania tego wszystkiego. Innymi słowy, przynajmniej możesz zobaczyć tę postać Które nie są obsługiwane poprawnie!
Odwróciłbym twoje pytanie do góry nogami i powiedziałbym, że cały przeklęty kod Unicode powinien być uważany za szkodliwy i każdy powinien używać 8-bitowego kodowania, z wyjątkiem Widziałem (w ciągu ostatnich 20 lat), do czego to prowadzi: okropne zamieszanie związane z różnymi kodowaniami ISO 8859 oraz całym zestawem kodowań używanych dla cyrylicy i zestawu EBCDIC, a także… cóż, Unicode dla wszystkich jego błędów przebija to . Gdyby to nie był taki paskudny kompromis między różnymi krajami, nieporozumienia.
Komentarze