Kommentarer
- Ikke rigtig korrekt. Jeg forklarer, hvis du skriver " שָׁ " det sammensatte tegn, der består af " ש ", " ָ " og " ׁ ", vokaler, så fjernelse af hver af dem er logisk, du fjerner et kodepunkt, når du trykker på " backspace " og fjern alle tegn inklusive vokaler, når du trykker på " del ". Men du producerer aldrig ulovlig tilstand af tekst – ulovlige kodepunkter. Situationen, når du trykker på backspace og får ulovlig tekst, er forkert.
- CiscoIPPhone: Hvis en fejl " rapporteres flere forskellige gange, af mange forskellige mennesker ", og et par år senere skriver en udvikler på en dev-blog, at " Tro det eller ej, opførslen er for det meste forsætlig! ", så (mildt sagt) har jeg tendens til at tro, at det ' sandsynligvis ikke er den bedste designbeslutning, der nogensinde er taget. 🙂 Bare fordi det ' s forsætligt betyder ikke ' t det ' er ikke en fejl.
- Fantastisk indlæg. UTF-16 er faktisk " det værste af begge verdener ": UTF8 har variabel længde, dækker hele Unicode, kræver en transformationsalgoritme til og fra rå kodepunkter, begrænser til ASCII, og det har ingen problemer med endenhed. UTF32 har fast længde, kræver ingen transformation, men tager mere plads og har problemer med endianness. Indtil videre er det godt, at du kan bruge UTF32 internt og UTF8 til serialisering. Men UTF16 har ingen fordele: Det ' er endianafhængigt, det ' s variable længde, det tager masser af plads, det ' er ikke ASCII-kompatibel. Den nødvendige indsats for at håndtere UTF16 korrekt kunne bruges bedre på UTF8.
- @Ian: UTF-8 har IKKE de samme forbehold som UTF-8. Du kan ikke have surrogater i UTF-8. UTF-8 maskerer sig ikke som noget, det ikke er, men de fleste programmører, der bruger UTF-16, bruger det forkert. Jeg ved. Jeg ' har set dem igen og igen og igen og igen.
- Også UTF-8 ' t har problemet, fordi alle behandler det som en kodning med variabel bredde. Årsagen til, at UTF-16 har problemet er, at alle behandler det som en kodning med fast bredde.
Svar
Dette er et gammelt svar.
Se UTF-8 overalt for de seneste opdateringer.
Udtalelse: Ja, UTF-16 skal betragtes som skadelig . Grunden til, at den eksisterer, er, at der for en tid siden tidligere var en misforstået tro på, at widechar vil være, hvad UCS-4 nu er.
På trods af UTF-8s “anglo-centrisme” er det bør betragtes som den eneste nyttige kodning til tekst. Man kan argumentere for, at kildekoder for programmer, websider og XML-filer, OS-filnavne og andre computer-til-computer tekstgrænseflader aldrig skulle have eksisteret. Men når de gør det, er tekst ikke kun for menneskelige læsere.
På den anden side er UTF-8 overhead en lille pris at betale, mens den har betydelige fordele. Fordele som f.eks. Kompatibilitet med ukendt kode, der bare sender strenge med char*
. Dette er en fantastisk ting. Der er få nyttige tegn, der er KORTERE i UTF-16, end de er i UTF-8.
Jeg tror, at alle andre kodninger vil dø i sidste ende. Dette involverer, at MS-Windows, Java, ICU, python stop med at bruge det som deres favorit. Efter lang forskning og diskussioner forbyder udviklingskonventionerne på mit firma at bruge UTF-16 hvor som helst undtagen OS API-opkald, og dette på trods af vigtighed af ydeevne i vores applikationer og det faktum, at vi bruger Windows. Konverteringsfunktioner blev udviklet til at konvertere altid-antaget-UTF8 std::string
s til native UTF-16, som Windows selv understøtter ikke korrekt .
Til folk, der siger “ brug det, der er nødvendigt, hvor det er nødvendigt “, siger jeg: der er en enorm fordel ved at bruge den samme kodning overalt, og jeg ser ingen tilstrækkelig grund til at gør det ellers. Jeg synes især, at tilføjelse af wchar_t
til C ++ var en fejltagelse, og det samme er Unicode-tilføjelserne til C ++ 0x. Hvad der dog skal kræves af STL-implementeringer er, at std::string
eller char*
parameter betragtes som unicode-kompatibel.
Jeg er også imod “ brug hvad du vil “tilgang. Jeg ser ingen grund til sådan frihed. Der er nok forvirring om emnet for tekst, hvilket resulterer i al denne ødelagte software. Når det er sagt, er jeg overbevist om, at programmører endelig skal nå til enighed om UTF-8 som en rigtig måde. (Jeg kommer fra et ikke-ascii-talende land og voksede op på Windows, så det forventes sidst, at jeg angriber UTF-16 på baggrund af religiøse grunde.)
Jeg vil gerne dele mere information om, hvordan jeg laver tekst på Windows, og hvad jeg anbefaler alle andre til kompileringstidskontrolleret unicode-korrekthed, brugervenlighed og bedre multi-platformness af koden. Forslaget adskiller sig væsentligt fra, hvad der normalt anbefales som den rigtige måde at bruge Unicode på windows på. Alligevel resulterede en dybtgående undersøgelse af disse anbefalinger i den samme konklusion. Så her går:
- Brug ikke
wchar_t
ellerstd::wstring
et andet sted end tilstødende punkt til APIer, der accepterer UTF-16. - Brug ikke
_T("")
ellerL""
UTF-16 bogstaver (Disse skal IMO tages ud af standarden , som en del af UTF-16 udfasning). - Brug ikke typer, funktioner eller deres derivater, der er følsomme over for
_UNICODE
-konstanten, såsomLPTSTR
ellerCreateWindow()
. - Alligevel er
_UNICODE
altid defineret, til undgå at videregivechar*
strenge til WinAPI bliver stille kompileret -
std::strings
ogchar*
hvor som helst i programmet betragtes som UTF-8 (hvis ikke andet er sagt) - Alle mine strenge er
std::string
, selvom du kan videregive char * eller streng tilconvert(const std::string &)
. -
bruger kun Win32-funktioner, der accepterer widechars (
LPWSTR
). Aldrig dem, der acceptererLPTSTR
ellerLPSTR
. Videregiv parametre på denne måde:::SetWindowTextW(Utils::convert(someStdString or "string litteral").c_str())
(Politikken bruger nedenstående konverteringsfunktioner.)
-
Med MFC-strenge :
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);
-
Arbejde med filer, filnavne og fstream på Windows:
- Gå aldrig
std::string
ellerconst char*
filnavnargumenter tilfstream
familie. MSVC STL understøtter ikke UTF-8-argumenter, men har en ikke-standard udvidelse, som skal bruges som følger: -
Konverter
std::string
argumenter tilstd::wstring
medUtils::Convert
:std::ifstream ifs(Utils::Convert("hello"), std::ios_base::in | std::ios_base::binary);
Vi bliver nødt til manuelt fjern konverteren, når MSVCs holdning til
fstream
ændres. - Denne kode er ikke multi-platform og skal muligvis ændres manuelt i fremtiden
- Se
fstream
forsknings- / diskussionssag 4215 for unicode for mere info. - Producer aldrig tekstoutputfiler med ikke-UTF8-indhold
- Undgå at bruge
fopen()
af RAII / OOD-grunde. Brug om nødvendigt_wfopen()
og WinAPI-konventionerne ovenfor.
- Gå aldrig
// 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 }
Kommentarer
- Jeg kan ' ikke er enig. Fordelene ved utf16 frem for utf8 for mange asiatiske sprog dominerer helt de punkter, du laver. Det er naivt at håbe, at japanerne, thailænderne, kineserne osv. Vil opgive denne kodning. De problematiske sammenstød mellem tegnsæt er, når tegnsættene mest ligner hinanden, undtagen med forskelle. Jeg foreslår at standardisere på: fast 7bit: iso-irv-170; 8bit variabel: utf8; 16bit variabel: utf16; 32bit fast: ucs4.
- @Charles: tak for dit input. Sandt nok er nogle BMP-tegn længere i UTF-8 end i UTF-16. Men lad os ' se det ind: problemet er ikke i bytes, som kinesiske BMP-tegn tager, men softwaredesignets kompleksitet, der opstår. Hvis en kinesisk programmør alligevel skal designe til tegn med variabel længde, ser det ud til, at UTF-8 stadig er en lille pris at betale sammenlignet med andre variabler i systemet. Han bruger muligvis UTF-16 som en komprimeringsalgoritme, hvis pladsen er så vigtig, men selv da vil det ikke være nogen match for LZ, og efter LZ eller anden generisk kompression tager begge omtrent samme størrelse og entropi.
- Hvad jeg grundlæggende siger er, at forenkling, der tilbydes ved at have en kodning, der også er kompatibel med eksisterende char * -programmer, og som også er den mest populære i dag for alt, er utænkelig.Det er næsten som i gode gamle " almindelig tekst " dage. Vil du åbne en fil med et navn? Ingen grund til at være ligeglad med, hvilken slags unicode du laver osv. Jeg foreslår, at vi, udviklere, begrænser UTF-16 til meget specielle tilfælde med alvorlig optimering, hvor en lille smule ydeevne er værd at arbejde i mandlige måneder.
- Linux har haft et specifikt krav, når man vælger at bruge UTF-8 internt: kompatibilitet med Unix. Windows behøvede ikke ', og derfor, da udviklerne implementerede Unicode, tilføjede de UCS-2 versioner af næsten alle funktioner, der håndterer tekst og fik multibyte til at konvertere til UCS-2 og kalde de andre. De erstatter senere UCS-2 med UTF-16. Linux på den anden side holdt sig til 8-bit kodninger og brugte således UTF-8, da det ' er det rigtige valg i så fald.
- @Pavel Radzivilovsky : BTW, dine skrifter om " Jeg tror, at alle andre kodninger vil dø i sidste ende. Dette indebærer, at MS-Windows, Java, ICU, python holder op med at bruge det som deres favorit. " og " Især synes jeg at tilføje wchar_t til C ++ var en fejltagelse, og det samme er tilføjelserne til unicode til C ++ Ox. " er enten ret naive eller meget meget arrogante . Og dette kommer fra nogen, der koder hjemme med en Linux, og som er tilfredse med UTF-8-tegnene. For at sige det direkte: Det vandt ' t ske .
Svar
Unicode-kodepunkter er ikke tegn! Nogle gange er de ikke engang tegn (visuelle former) .
Nogle eksempler:
- Romerske kodepunkter som “ⅲ”. (Et enkelt tegn, der ligner “iii”.)
- Accenterede tegn som “á”, som enten kan repræsenteres som et enkelt kombineret tegn “\ u00e1” eller et tegn og adskilt diakritisk “\ u0061 \ u0301 “.
- Tegn som græsk lille bogstaver sigma, som har forskellige former for mellem (” σ “) og slutning (” ς “) af ordpositioner, men som skal betragtes som synonymer for søgning.
- Unicode diskretionær bindestreg U + 00AD, som måske eller måske ikke vises visuelt, afhængigt af kontekst, og som ignoreres ved semantisk søgning.
De eneste måder at få Unicode-redigering på ret er at bruge et bibliotek skrevet af en ekspert , eller blive ekspert og skrive et selv. Hvis du bare tæller kodepunkter, lever du i en tilstand af synd.
Kommentarer
- Dette. Meget meget dette. UTF-16 kan forårsage problemer, men selv brug af UTF-32 igennem kan (og vil) stadig give dig problemer.
- Hvad er en karakter? Du kan definere et kodepunkt som et tegn og klare det stort set fint. Hvis du mener en brugersynlig glyph, er det noget andet.
- @tchrist sikker på at tildele plads er denne definition fint, men for noget andet? Ikke så meget. Hvis du håndterer et kombinerende tegn som et eneste tegn (dvs. for en sletning eller " skal du tage de første N-tegn " handling) du ' Jeg får mærkelig og forkert opførsel. Hvis et kodepunkt kun har betydning, når det kombineres med mindst et andet, kan du ' t håndtere det alene på en fornuftig måde.
- @Pacerier, dette er sent til festen, men jeg er nødt til at kommentere det. Nogle sprog har meget store sæt potentielle kombinationer af diakritikere (jf. Vietnamesisk, dvs. mệt đừ). At have kombinationer i stedet for et tegn pr. Diakritisk er meget nyttigt.
- en lille note om terminologi: kodepunkter gør svarer til unicode-tegn ; hvad Daniel taler om her er brugeropfattede tegn , der svarer til unicode-grafemklynger
Svar
Der er en simpel tommelfingerregel på, hvilken Unicode Transformation Form (UTF) der skal bruges: – utf-8 til opbevaring og kommunikation – utf-16 til databehandling – du går muligvis med utf-32, hvis det meste af platform-APIet, du bruger, er utf-32 (almindeligt i UNIX-verdenen).
De fleste systemer bruger i dag utf-16 (Windows, Mac OS, Java, .NET, ICU , Qt). Se også dette dokument: http://unicode.org/notes/tn12/
Tilbage til “UTF-16 som skadelig”, Jeg vil sige: bestemt ikke.
Folk, der er bange for surrogater (tænker at de omdanner Unicode til en kodning med variabel længde) forstår ikke de andre (langt større) kompleksiteter, der gør kortlægning mellem tegn og et Unicode-kodepunkt meget komplekst: kombinerer tegn, ligaturer, variationsvælgere, kontroltegn osv.
Læs bare denne serie her http://www.siao2.com/2009/06/29/9800913.aspx og se, hvordan UTF-16 bliver et let problem.
Kommentarer
- Tilføj venligst nogle eksempler, hvor UTF-32 er almindelig i UNIX-verdenen!
- Nej, det gør du ikke ønsker at bruge UTF-16 til databehandling. Det ' er en smerte i røvet. Det har alle ulemperne ved UTF-8, men ingen af fordelene. Både UTF-8 og UTF-32 er klart bedre end det onde hack, der tidligere var kendt som fru UTF-16, hvis pigenavn var UCS-2.
- Jeg fandt i går netop en fejl i Java-kernestringklassens
equalsIgnoreCase
metode (også andre i strengklassen), der aldrig ville have været der, hvis Java havde brugt UTF-8 eller UTF-32. Der er millioner af disse sovende bomber i enhver kode, der bruger UTF-16, og jeg er træt af dem. UTF-16 er en ondskabsfuld pox, der plager vores software med snigende bugs for evigt og altid. Det er tydeligt skadeligt og bør udfases og forbydes. - @tchrist Wow så en ikke-surrogat opmærksom funktion (fordi den blev skrevet, da der ikke var nogen, og er desværre dokumenteret på en sådan måde, der gør det sandsynligvis umuligt at tilpasse – det specificerer .toUpperCase (char)) vil resultere i forkert opførsel? Du ' er opmærksom på, at en UTF-32-funktion med et forældet kodepunktkort ikke ' ikke kan håndtere dette bedre? Også hele Java API håndterer surrogater ikke særlig godt, og de mere indviklede punkter om Unicode overhovedet ikke – og med senere vil den anvendte kodning slet ikke ' være vigtig.
- -1: En ubetinget
.Substring(1)
i .NET er et trivielt eksempel på noget, der bryder understøttelsen for alle ikke-BMP Unicode. Alt der bruger UTF-16 har dette problem; det ' er for let til at behandle det som en kodning med fast bredde, og du ser problemer for sjældent. Det gør det til en aktiv skadelig kodning, hvis du vil støtte Unicode.
Svar
Ja, absolut.
Hvorfor? Det har at gøre med udøvelse af kode .
Hvis du ser på disse codepoint-brugsstatistikker på et stort korpus af Tom Christiansen vil du se, at trans-8bit BMP-kodepunkter bruges flere ordrer, hvis størrelsen er større end ikke-BMP-kodepunkter:
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
Tag TDD-diktummet: “Utestet kode er brudt kode”, og omformuler den som “uudøvet kode er brudt kode”, og tænk, hvor ofte programmører har at gøre med kodepunkter, der ikke er BMP.
Fejl relateret til ikke at behandle UTF-16 som en kodning med variabel bredde er meget mere tilbøjelige til at gå ubemærket hen end de tilsvarende fejl i UTF-8 . Nogle programmeringssprog stadig garanterer ikke at give dig UTF-16 i stedet for UCS-2, og nogle såkaldte programmeringssprog på højt niveau giver adgang til kodeenheder i stedet for kodepunkter (selv C formodes at give dig adgang til kodepunkter, hvis du bruger wchar_t
, uanset hvad nogle plat formularer kan gøre).
Kommentarer
- " Fejl relateret til ikke at behandle UTF-16 som en kodning med variabel bredde er meget mere tilbøjelige til at gå ubemærket hen end de tilsvarende fejl i UTF-8. " Dette er kernen i problemet og dermed det korrekte svar.
- Præcis. Hvis din UTF-8-håndtering er borked, er det ' straks indlysende. Hvis din UTF-8-håndtering borkes, vil du ' kun bemærke, hvis du lægger sjældne Han-tegn eller matematiske symboler i brug.
- Meget sandt, men på den anden side hånd, hvad er enhedstest til, hvis du skulle stole på held med at finde fejl i mindre hyppige tilfælde?
- @musiphil: hvornår oprettede du sidst en enhedstest for ikke-BMP-tegn?
- For at uddybe min tidligere erklæring: selv med UTF-8 kan du ikke være sikker på, at du har dækket alle sager efter kun at have set nogle arbejdseksempler. Samme med UTF-16: du skal teste, om din kode fungerer både med ikke-surrogater og med surrogater. (Nogen kan endda argumentere for, at UTF-8 har mindst fire større sager, mens UTF-16 kun har to.)
Svar
Jeg vil foreslå, at tænkning af UTF-16 måske betragtes som skadelig, siger at du er nødt til at få en større forståelse for unicode .
Da jeg er blevet nedstemt for at præsentere min mening om et subjektivt spørgsmål, så lad mig uddybe. Hvad præcist er det, der generer dig ved UTF-16? Foretrækker du, at alt var kodet i UTF-8? UTF-7? Eller Hvad med UCS-4? Visse applikationer er selvfølgelig ikke designet til at håndtere everysingle tegnkode derude – men de er nødvendige, især i nutidens globale informationsdomæne, til kommunikation mellem internationale grænser.
Men virkelig, hvis du føler at UTF-16 skal betragtes som skadelig, fordi det er forvirrende eller kan implementeres forkert (unicode kan bestemt være), hvilken metode til tegnkodning ville da blive betragtet som ikke-skadelig?
REDIGERING: For at præcisere: Hvorfor betragte forkert implementering af en standard som en afspejling af kvaliteten af selve standarden? Som andre efterfølgende har bemærket, betyder det kun, at en applikation bruger et værktøj uhensigtsmæssigt, ikke at værktøjet i sig selv er defekt. Hvis det var tilfældet, kunne vi sandsynligvis sige ting som “var nøgleord betragtes som skadeligt” eller “trådning betragtes som skadeligt”. Jeg tror, at spørgsmålet forveksler standardens kvalitet og karakter med de vanskeligheder, som mange programmører har med at implementere og bruge det ordentligt, hvilket jeg føler stammer mere fra deres manglende forståelse for, hvordan unicode fungerer, snarere end selve unicode.
Kommentarer
- -1: Hvad med at adressere nogle af Artyom ' s objekter ons, snarere end blot at nedladende ham?
- BTW: Da jeg begyndte at skrive denne artikel, ville jeg næsten skrive " Skal Joel på Softeare-artiklen fra Unicode overvejes skadelig " fordi der er mange fejl. For eksempel: utf-8-kodning tager op til 4 tegn og ikke 6. Det skelner heller ikke mellem UCS-2 og UTF-16, der er virkelig forskellige – og forårsager faktisk de problemer, jeg taler om.
- Det skal også bemærkes, at da Joel skrev denne artikel, var UTF-8-standarden WAS 6 byte, ikke 4. RFC 3629 ændrede standarden til 4 byte flere måneder, efter at han skrev artiklen. Som det meste på internettet betaler det sig at læse fra mere end én kilde og være opmærksom på alderen på dine kilder. Linket var ikke ' t beregnet til at være " slutningen alle være alle " snarere et udgangspunkt.
- Jeg ville billede: utf-8 eller utf-32 der er: kodning af variabel længde i næsten alle tilfælde (inklusive BMP) eller altid kodning med fast længde.
- @iconiK: Vær ikke fjollet. UTF-16 er absolut ikke de facto -standarden for behandling af tekst. Vis mig en programmeringssprog, der er mere velegnet til tekstbehandling, som Perl, som altid har (godt, i mere end et årti) brugte abstrakte tegn med en underliggende UTF-8-repræsentation internt. På grund af dette håndterer hvert Perl-program automatisk alle Unicode uden at brugeren konstant skal abe rundt med idiotiske surrogater. Længden af en streng er dens antal i kodepunkter, ikke kodeenheder. Alt andet er ren dumhed, der sætter baglæns i bagudkompatibilitet.
Svar
Der er ikke noget galt med Utf- 16 kodning. Men sprog, der behandler 16-bit-enhederne som tegn, bør sandsynligvis betragtes som dårligt designet. At have en type med navnet “char
“, som ikke altid repræsenterer et tegn, er ret forvirrende. Da de fleste udviklere forventer, at en char-type repræsenterer et kodepunkt eller tegn, vil meget kode sandsynligvis bryde, når de udsættes for tegn, beyound BMP.
Bemærk dog, at selv brug af utf-32 ikke betyder, at hver 32- bit kode punkt vil altid repræsentere et tegn. På grund af kombination af tegn kan en faktisk karakter bestå af flere kodepunkter. Unicode er aldrig trivielt.
BTW. Der er sandsynligvis den samme klasse af bugs med platforme og applikationer, som forventer, at tegn skal være 8-bit, som bliver fodret med Utf-8.
Kommentarer
- I Java ' sager, hvis du ser på deres tidslinje ( java.com/en/javahistory/timeline.jsp), ser du, at den primære udvikling af String skete, mens Unicode var 16 bit (det ændrede sig i 1996). De måtte boltre på evnen til at håndtere ikke-BMP-kodepunkter, og dermed forvirringen.
- @Kathy: Ikke rigtig en undskyldning for C #. Generelt er jeg enig i, at der skal være en
CodePoint
type, der holder et enkelt kodepunkt (21 bit), enCodeUnit
type, der holder en enkelt kodeenhed (16 bits til UTF-16) og enCharacter
-type ville ideelt set skulle understøtte en komplet grafeme. Men det gør det funktionelt svarende til etString
… - Dette svar er næsten to år gammelt, men jeg kan ' t hjælpe med at kommentere det. " At have en type med navnet ' char ' som ikke altid repræsenterer et tegn, er smuk forvirrende. " Og alligevel bruger folk det hele tiden i C og lignende til at repræsentere heltalsdata, der kan lagres i en enkelt byte.
- Og jeg ' har set et parti af C-kode, der ikke ' t håndterer tegnkodning korrekt.
- C # har en anden undskyldning: det blev designet til Windows, og Windows blev bygget på UCS-2 (det ' er meget irriterende, at selv i dag kan Windows APIer ikke understøtter UTF-8). Plus, jeg tror, at Microsoft ønskede Java-kompatibilitet (.NET 1.0 havde et Java-kompatibilitetsbibliotek, men de droppede Java-support meget hurtigt – jeg ' gætter på, at dette skyldes Sun ' sagsanlæg mod MS?)
Svar
Mit personlige valg er at altid bruge UTF-8. Det er standarden på Linux til næsten alt. Det er bagudkompatibelt med mange ældre apps. Der er en meget minimal overhead med hensyn til ekstra plads brugt til ikke-latinske tegn i forhold til de andre UTF-formater, og der er en betydelig besparelse i plads til latinske tegn. På nettet er latinske sprog herredømme, og jeg tror, de vil gøre det i overskuelig fremtid. Og for at adressere et af hovedargumenterne i det oprindelige indlæg: næsten enhver programmør er klar over, at UTF-8 undertiden vil have multi-byte-tegn i det. Ikke alle behandler dette korrekt, men de er normalt opmærksomme på, hvilket er mere, end der kan siges om UTF-16. Men selvfølgelig skal du vælge den, der passer bedst til din ansøgning. Derfor er der mere end en i første omgang.
Kommentarer
- UTF-16 er enklere for alt inden i BMP, at ' hvorfor det bruges så vidt. Men jeg ' Jeg er også fan af UTF-8, den har heller ingen problemer med byte rækkefølge, hvilket fungerer til sin fordel.
- Teoretisk set ja. I praksis er der sådanne ting som f.eks. UTF-16BE, hvilket betyder UTF-16 i stor endian uden stykliste. Dette er ikke nogle ting, jeg har lavet, dette er en faktisk kodning tilladt i ID3v2.4 tags (ID3v2 tags suger, men er desværre meget brugt). Og i sådanne tilfælde skal du definere sluttheden eksternt, fordi selve teksten ikke ' indeholder styklisten. UTF-8 er altid skrevet på én måde, og det har ikke ' et sådant problem.
- Nej, UTF-16 er ikke enklere. Det er sværere. Det vildleder og bedrager dig til at tro, at det er fast bredde. Al sådan kode er brudt og det hele, fordi du ikke bemærker, før det er for sent. CASE IN POINT: Jeg fandt lige endnu en dum UTF-16-fejl i Java-kernebibliotekerne i går, denne gang i String.equalsIgnoreCase, som blev efterladt i UCS-2 bagved buggery, og fejler således på 16/17 gyldige Unicode-kodepunkter. Hvor længe har den kode eksisteret? Ingen undskyldning for, at det er buggy. UTF-16 fører til ren dumhed og en ulykke, der venter på at ske. Kør skrigende fra UTF-16.
- @tchrist Man skal være en meget uvidende udvikler for ikke at vide, at UTF-16 ikke har en fast længde. Hvis du starter med Wikipedia, vil du læse følgende helt øverst: " Det producerer et resultat med variabel længde af enten en eller to 16-bit kodeenheder pr. Kodepunkt ". Ofte stillede spørgsmål i Unicode siger det samme: unicode.org/faq//utf_bom.html#utf16-1 . Jeg ved ' ikke, hvordan UTF-16 kan bedrage nogen, hvis det står overalt, at det har variabel længde. Med hensyn til metoden blev den aldrig designet til UTF-16 og skulle ikke ' ikke betragtes som Unicode, så enkel som den.
- @tchrist Har du en kilde til din statistik? Skønt hvis gode programmerere er knappe, synes jeg det er godt, fordi vi bliver mere værdifulde. 🙂 Hvad angår Java APIerne, kan char-baserede dele i sidste ende blive udfaset, men dette er ikke en garanti for, at de ikke vil ' t bruges. Og de vil bestemt ikke fjerne ' af kompabilitetsårsager.
Svar
Nå, der er en kodning, der bruger symboler i fast størrelse. Jeg mener bestemt UTF-32. Men 4 bytes for hvert symbol er for meget spildt plads, hvorfor skulle vi bruge det i hverdagssituationer?
Efter min mening fremgår de fleste problemer af det faktum, at noget software faldt bag Unicode-standarden, men var ikke hurtige til at rette op på situationen. Opera, Windows, Python, Qt – alle dukkede op, før UTF-16 blev vidt kendt eller endda opstod. Jeg kan dog bekræfte, at der i Opera, Windows Stifinder og Notesblok ikke længere er problemer med tegn uden for BMP (i det mindste på min pc). Men alligevel, hvis programmer ikke genkender surrogatpar, så bruger de ikke UTF-16. Uanset hvilke problemer der opstår ved at håndtere sådanne programmer, har de intet at gøre med selve UTF-16.
Jeg synes dog, at problemerne med ældre software med kun BMP-understøttelse er noget overdrevne. Tegn uden for BMP findes kun i meget specifikke tilfælde og områder. Ifølge Officielle Ofte stillede spørgsmål om Unicode , “selv i østasiatisk tekst, bør forekomsten af surrogatpar i gennemsnit være langt mindre end 1% af al tekstlagring”.Naturligvis bør tegn uden for BMP ikke overses fordi et program ellers ikke er Unicode-kompatibelt, men de fleste programmer er ikke beregnet til at arbejde med tekster, der indeholder sådanne tegn. Det er derfor, hvis de ikke gør det t støtte det, det er ubehageligt, men ikke en katastrofe.
Lad os nu overveje alternativet. Hvis UTF-16 ikke eksisterede, ville vi ikke have en kodning, der er velegnet til ikke-ASCII-tekst, og al den software, der er oprettet til UCS-2, skal redesignes fuldstændigt for at forblive Unicode-kompatibel. Sidstnævnte ville sandsynligvis kun bremse Unicode-adoption. Vi ville heller ikke have været i stand til at opretholde kompatibilitet med tekst i UCS-2 som UTF-8 gør i forhold til ASCII.
Nu, når man lægger alle de ældre problemer til side, hvad er argumenterne mod kodningen i sig selv? Jeg tvivler virkelig på, at udviklere i dag ikke ved, at UTF-16 har variabel længde, det er skrevet overalt, der begynder med Wikipedia. UTF-16 er meget mindre vanskeligt at analysere end UTF-8, hvis nogen påpegede kompleksitet som et muligt problem. Det er også forkert at tro, at det er let at rode med at bestemme strenglængden kun i UTF-16. Hvis du bruger UTF-8 eller UTF-32, skal du stadig være opmærksom på, at et Unicode-kodepunkt ikke nødvendigvis betyder et tegn. Bortset fra det tror jeg ikke, at der er noget væsentligt imod kodningen.
Derfor synes jeg ikke, at selve kodningen skal betragtes som skadelig. UTF-16 er et kompromis mellem enkelhed og kompakthed, og der er ingen skade i ved hjælp af, hvad der er nødvendigt, hvor det er nødvendigt I nogle tilfælde skal du forblive kompatibel med ASCII, og du har brug for UTF-8, i nogle tilfælde vil du arbejde med arbejde med Han-ideografier og spare plads ved hjælp af UTF-16, i nogle tilfælde har du brug for universelle repræsentationer af tegn, der bruger en fast -længdekodning. Brug hvad der er mere passende, bare gør det ordentligt.
Kommentarer
- At ' er en ret blinkende, anglo-centreret visning, Malcolm. Næsten på niveau med " ASCII er god nok for USA – resten af verden bør passe ind i os ".
- Faktisk ' m fra Rusland og støder på kyrillikere hele tiden (inklusive mine egne programmer), så jeg don ' Jeg tror ikke, jeg har en anglo-centreret opfattelse. 🙂 At nævne ASCII er ikke helt passende, fordi det ' ikke er Unicode og ikke ' t understøtter specifikke tegn. UTF-8, UTF-16, UTF-32 understøtter de samme internationale tegnsæt, de er kun beregnet til brug i deres specifikke områder. Og dette er nøjagtigt mit punkt: Hvis du bruger mest engelsk, skal du bruge UTF-8, hvis du bruger mest kyrillik, skal du bruge UTF-16, hvis du bruger gamle sprog, skal du bruge UTF-32. Ganske enkelt.
- " Ikke sandt, asiatiske scripts som japansk, kinesisk eller arabisk hører også til BMP. BMP i sig selv er faktisk meget stort og bestemt stort nok til at inkludere alle de scripts, der bruges i dag " Dette er alt sammen forkert. BMP indeholder 0xFFFF tegn (65536). Kinesisk alene har mere end det. Kinesiske standarder (GB 18030) har mere end det. Unicode 5.1 tildelte allerede mere end 100.000 tegn.
- @Marcolm: " BMP i sig selv er faktisk meget stor og bestemt stor nok til at inkludere alle de scripts, der bruges i dag " Ikke sandt. På dette tidspunkt tildelte Unicode allerede omkring 100K tegn, meget mere end BMP kan rumme. Der er store klumper af kinesiske tegn uden for BMP. Og nogle af dem kræves af GB-18030 (obligatorisk kinesisk standard). Andet kræves af (ikke-obligatoriske) japanske og koreanske standarder. Så hvis du prøver at sælge noget på disse markeder, har du brug for mere end BMP-support.
- Alt, der bruger UTF-16, men kun kan håndtere smalle BMP-tegn, bruger faktisk ikke UTF-16. Det er buggy og brudt. Forudsætningen for OP er sund: UTF-16 er skadelig, fordi det fører til ï ve folk til at skrive brudt kode. Enten kan du håndtere Unicode-tekst, eller så kan du ikke. Hvis du ikke kan, vælger du et undersæt, der er lige så dumt som kun ASCII-tekstbehandling.
Svar
Års med Windows-internationaliseringsarbejde, især på østasiatiske sprog, kan have ødelagt mig, men jeg læner mig mod UTF-16 for intern-til-programmet-repræsentation af strenge og UTF-8 til netværks- eller fillagring af almindelig tekst- som dokumenter. UTF-16 kan dog normalt behandles hurtigere på Windows, så det er den primære fordel ved at bruge UTF-16 i Windows.
At gøre springet til UTF-16 forbedrede dramatisk tilstrækkeligheden af gennemsnitlig produkthåndtering international tekst.Der er kun få snævre tilfælde, hvor surrogatparene skal overvejes (sletninger, indsættelser og linjebrydning, dybest set), og gennemsnittet er for det meste lige igennem. Og i modsætning til tidligere kodninger som JIS-varianter begrænser UTF-16 surrogatpar til et meget snævert interval, så kontrollen er virkelig hurtig og fungerer fremad og bagud.
Indrømmet, det er omtrent lige så hurtigt korrekt – kodet UTF-8 også. Men der er også mange ødelagte UTF-8 applikationer, der forkert koder for surrogatpar som to UTF-8 sekvenser. UTF-8 garanterer heller ikke frelse.
IE håndterer surrogatpar med rimelighed siden 2000 eller deromkring, selvom det typisk konverterer dem fra UTF-8 sider til en intern UTF-16-repræsentation; I “Jeg er ret sikker på, at Firefox også har det rigtigt, så jeg er ligeglad med, hvad Opera gør.
UTF-32 (også kaldet UCS4) er meningsløs for de fleste applikationer, da det er så pladskrævende, så det er stort set en nonstarter.
Kommentarer
- Jeg fik ikke ' ikke helt din kommentar til UTF-8 og surrogatpar. Surrogatpar er kun et begreb, der er meningsfuldt i UTF-16-kodningen, ikke? Måske kan kode, der konverteres direkte fra UTF-16-kodning til UTF-8-kodning, muligvis få dette forkert, og i det tilfældet, er problemet forkert at læse UTF-16, ikke skrive UTF-8. Er det rigtigt?
- Hvad Jason ' taler om er software, der implementerer bevidst UTF-8 på den måde: Opret et surrogatpar, derefter UTF-8 da kode hver halvdel separat. Det korrekte navn for den kodning er CESU-8, men Oracle (f.eks.) Gengiver det forkert som UTF-8. Java anvender en lignende ordning til objektserialisering, men den ' er tydeligt dokumenteret som " Modificeret UTF-8 " og kun til intern brug. (Hvis vi bare kunne få folk til at LÆSE dokumentationen og stoppe med at bruge DataInputStream # readUTF () og DataOutputStream # writeUTF () uhensigtsmæssigt …)
- AFAIK, UTF-32 er stadig kodning med variabel længde, og ikke lig med UCS4, som er et specifikt område for kodepunkt.
- @Eonil, UTF-32 kan kun nogensinde skelnes fra UCS4, hvis vi har en Unicode-standard, der har noget som en UCS5 eller større.
- @JasonTrue Stadig, kun resultaterne er lige tilfældige, ikke garanteret af design. Den samme ting skete i 32-bit hukommelsesadressering, Y2K, UTF16 / UCS2. Eller har vi nogen garanti for denne lighed? Hvis vi har det, vil jeg gerne bruge det. Men jeg vil ikke ' ikke skrive en mulig knækkelig kode. Jeg skriver en karakterniveaukode, og manglen på en garanteret måde at omkode mellem UTF < – > kodepunkt bugter mig meget .
Svar
UTF-8 er bestemt vejen at gå, muligvis ledsaget af UTF-32 til intern brug i algoritmer, der har brug for højtydende tilfældig adgang (men som ignorerer kombinationen af tegn).
Både UTF-16 og UTF-32 (såvel som deres LE / BE-varianter) lider af problemer med endianess, så de burde må aldrig bruges eksternt.
Kommentarer
- Tilfældig adgang til konstant tid er også mulig med UTF-8, brug bare kodeenheder snarere end kodepunkter. Måske har du brug for ægte tilfældig adgang til kodepunkt, men jeg ' har aldrig set en brugssag, og du ' er lige så sandsynlig, at du vil tilfældig grafem-klyngeadgang i stedet.
Svar
UTF-16? bestemt skadelig. Bare mit saltkorn her, men der er nøjagtigt tre acceptable kodninger for tekst i et program:
- ASCII: når man beskæftiger sig med ting på lavt niveau (f.eks. Mikrokontroller), der ikke har råd til noget bedre
- UTF8: lagring i medier med fast bredde, såsom filer
-
heltalskodepunkter (“CP”?): en matrix med de største heltal, der passer til dit programmeringssprog og platform (henfalder til ASCII i grænsen for lave resorces). Bør være int32 på ældre computere og int64 på noget med 64-bit adressering.
-
Selvfølgelig grænseflader til ældre kodebrug hvilken kodning der er behov for for at få den gamle kode til at fungere korrekt.
Kommentarer
- @simon buchan,
U+10ffff
max går ud af vinduet, når (ikke hvis) de løber tør for kodepunkter. Når det er sagt, er det sandsynligvis sikkert at bruge int32 på et p64-system til hastighed, da jeg tvivler på, at de ' vil overstigeU+ffffffff
før du er tvunget til at omskrive din kode til 128 bit-systemer omkring 2050. (Det er punktet med " brug det største int, der er praktisk " i modsætning til " største tilgængelige " (hvilket sandsynligvis ville være int256 eller bignums eller noget).) - @David: Unicode 5.2 koder for 107.361 kodepunkter.Der er 867.169 ubrugte kodepunkter. " når " bare er fjollet. Et Unicode-kodepunkt er defineret som et tal fra 0 til 0x10FFFF, en egenskab som UTF-16 afhænger af. (Også 2050 synes meget lavt at estimere 128-bit-systemer, når et 64-bit-system kan indeholde hele Internettet i det ' s adresseområde.)
- @David: Din " når " henviste til at løbe tør for Unicode-kodepunkter, ikke en 128-bit switch, som ja vil være i de næste par århundreder. I modsætning til hukommelse er der ingen eksponentiel vækst af tegn, så Unicode Consortium har specifikt garanteret, at de aldrig tildeler et kodepunkt over
U+10FFFF
. Dette er virkelig en af de situationer, hvor 21 bits er nok for nogen. - @Simon Buchan: I det mindste indtil første kontakt. 🙂
- Unicode bruges til at garantere, at der heller ikke er nogen kodepunkter over U + FFFF.
Svar
Unicode definerer kodepunkter op til 0x10FFFF (1.114.112 koder), alle applikationer kører i flersproget miljø med strenge / filnavne osv. skal håndtere det korrekt.
Utf-16 : dækker kun 1.112.064 koder. Selvom de i slutningen af Unicode er fra fly 15-16 (privat brugsområde). Det kan ikke vokse længere i fremtiden undtagen at bryde Utf-16 koncept.
Utf-8 : dækker teoretisk 2.216.757.376 koder. Nuværende interval af Unicode koder kan repræsenteres ved maksimalt 4 bytesekvens. Det lider ikke med byte rækkefølge problem, det er “kompatibelt” med ascii.
Utf-32 : dækker teoretisk 2 ^ 32 = 4.294.967.296 koder. I øjeblikket er det ikke kodet med variabel længde og vil sandsynligvis ikke være i fremtiden.
Disse fakta er selvforklarende. Jeg forstår ikke fortaler for generel brug af Utf-16 . Det er kodet med variabel længde (kan ikke tilgås via indeks), det har problemer med at dække hele Unicode selv i øjeblikket, byteordre skal håndteres osv. Jeg kan ikke se nogen fordel, bortset fra at den bruges indbygget i Windows og andre steder. Selvom det er sandsynligvis bedre at bruge Utf-8 og kun foretage konverteringer ved slutpunkterne, når du skriver multi-platformskode. på platformafhængig måde (som allerede foreslået). Når direkte adgang via indeks er nødvendigt, og hukommelse ikke er et problem, skal Utf-32 bruges.
Hovedproblemet er, at mange programmører, der beskæftiger sig med Windows Unicode = Utf-16 ikke engang kender eller ignorerer det faktum, at det er kodet med variabel længde.
Den måde, det normalt er på * nix platform er ret godt, c strenge (char *) fortolket som Utf-8 kodede, brede c strenge (wchar_t *) fortolket som Utf-32 .
Kommentarer
- Bemærk: UTF -16 dækker All Unicode, da Unicode Consortium besluttede, at 10FFFF er TOP-området for Unicode og definerede UTF-8 maksimal 4 bytes længde og eksplicit ekskluderet interval 0xD800-0xDFFF fra gyldigt kodepunkter, og dette interval bruges til oprettelse af surrogat par. Så enhver gyldig Unicode-tekst kan repræsenteres med hver af disse kodninger. Også om at vokse til fremtiden. ' Det ser ud til, at 1 million kodepunkter ikke ville være nok i nogen fjern fremtid.
- @Kerrek: Forkert: UCS-2 er ikke en gyldig Unicode indkodning. Alle UTF- * -kodninger kan pr. Definition repræsentere ethvert Unicode-kodepunkt, der er lovligt til udveksling. UCS-2 kan repræsentere langt færre end det plus et par flere. Gentag: UCS-2 er ikke en gyldig Unicode-kodning, noget mere end ASCII er.
- " Jeg forstår ikke at anbefale generel brug af Utf- 8 . Det er kodet med variabel længde (kan ikke tilgås med indeks) "
- @Ian Boyd, behovet for at få adgang til en strengs individuelle karakter i et tilfældigt adgangsmønster er utroligt overvurderet. Det er omtrent lige så almindeligt som at ønske at beregne diagonalen i en matrix med tegn, hvilket er super sjældent. Strenge behandles stort set altid sekventielt, og da adgang til UTF-8-char N + 1, givet at du er ved UTF-8, er char N er O (1), er der ikke noget problem. Der er overordentlig lidt behov for at gøre tilfældig adgang til strenge. Uanset om du synes, det er værd at opbevaringspladsen er at gå til UTF-32 i stedet for UTF-8, er din egen mening, men for mig er det i det hele taget et ikke-spørgsmål.
- @tchrist, jeg giver dine strenge behandles næsten altid sekventielt, hvis du inkluderer omvendt iteration som " sekventiel " og strækker det lidt yderligere sammenligning af den bageste ende af en streng til en kendt streng. To meget almindelige scenarier er trunkering af mellemrum fra slutningen af strenge og kontrol af filtypen i slutningen af en sti.
Svar
Føj dette til listen:
Det præsenterede scenario er simpelt (endnu mere simpelt, da jeg vil præsentere det her, end det oprindeligt var! ): 1.En WinForms TextBox sidder på en formular, tom. Den har en maks. Længde indstillet til 20 .
2. Brugeren skriver i TextBox eller måske indsætter tekst i den.
3. Uanset hvad du skriver eller indsætter i TextBox, er du begrænset til 20, selvom det sympatisk bipper ved tekst ud over 20 (YMMV her; jeg har ændret mit lydskema for at give mig den effekt!).
4.Den lille pakke tekst sendes derefter et andet sted for at starte et spændende eventyr.
Nu er dette et let scenarie, og enhver kan skrive dette op i sin fritid. Jeg skrev det bare op på flere programmeringssprog ved hjælp af WinForms, fordi jeg kede mig og aldrig havde prøvet det før. Og med tekst på flere faktiske sprog, fordi jeg er kablet på den måde og har flere tastaturlayouter end muligvis nogen i hele det freaking univers.
Jeg navngav endda formularen Magic Carpet Ride for at hjælpe med at forbedre kedsomheden.
Dette fungerede ikke, for hvad det er værd.
Så i stedet indtastede jeg følgende 20 tegn i min Magic Carpet Ride form:
0123401234012340123 𠀀
Uh oh.
Det sidste tegn er U + 20000, det første Udvidelse B ideografi til Unicode (alias U + d840 U + dc00, til sine nære venner, som han ikke skammer sig over at blive afskaffet, som det var foran) ….
Og nu har vi et boldspil.
For når TextBox. MaxLength taler om
Henter eller indstiller det maksimale antal tegn, der kan indtastes manuelt i tekstboksen.
hvad det virkelig betyder er
Får eller sæt det maksimale antal UTF-16 LE torsk De enheder, der kan indtastes manuelt i tekstboksen og vil nådesløst afkorte det levende crap ud af enhver streng, der prøver at spille søde spil med den sproglige karakteropfattelse, at kun en så besat som den Kaplan-fyr vil finde stødende komme ud mere!).
Jeg prøver at se om opdateringen af dokumentet ….
Almindelige læsere, der husk, at min UCS-2 til UTF-16 -serien vil bemærke min utilfredshed med den enkle forestilling om TextBox.MaxLength og hvordan det i det mindste skal håndtere dette tilfælde, hvor dets drakoniske opførsel skaber en ulovlig sekvens, en som andre dele af .Net Framework muligvis kaster et
- System.Text.EncoderFallbackException : Kan ikke oversætte Unicode-tegn \ uD850 ved indeks 0 til den angivne kodeside. *
undtagelse, hvis du sender denne streng andetsteds i .Net Framework (som min kollega Dan Thompson gjorde).
Nu okay, måske er den fulde UCS-2 til UTF-16-serien uden for rækkevidde for mange.
Men er ikke “t er det rimeligt at forvente, at TextBox.Text ikke producerer et System.String , der ikke får et andet stykke af .Net Framework til at kaste? Jeg mener, det er ikke som om der er en chance i form af en eller anden begivenhed på kontrollen, der fortæller dig om den kommende trunkering, hvor du nemt kan tilføje den smartere validering – validering, som selve kontrollen ikke har noget imod at gøre. Jeg ville gå så langt som at sige, at denne punk-kontrol bryder en sikkerhedskontrakt, der endda kan føre til sikkerhedsproblemer, hvis du kan klasse forårsage uventede undtagelser for at afslutte en applikation som en grov form for denial of service. Hvorfor skal nogen WinForms-proces eller -metode eller algoritme eller teknik giver ugyldige resultater?
Kilde: Michael S.Kaplan MSDN-blog
Kommentarer
- Tak, meget godt link! Jeg ' har føjet det til spørgsmålslisten i spørgsmålet.
Svar
Jeg vil ikke nødvendigvis sige, at UTF-16 er skadelig. Det er ikke elegant, men det tjener sit formål med bagudkompatibilitet med UCS-2, ligesom GB18030 gør med GB2312, og UTF-8 gør med ASCII.
Men at foretage en grundlæggende ændring af Unicodes struktur i midstream, efter at Microsoft og Sun havde bygget enorme APIer omkring 16-bit tegn, var skadeligt. Manglen på at sprede bevidstheden om ændringen var mere skadelig.
Kommentarer
- UTF-8 er et supersæt af ASCII , men UTF-16 er IKKE et supersæt af UCS-2. Selvom det næsten er et supersæt, resulterer en korrekt kodning af UCS-2 i UTF-8 i den afsky, der er kendt som CESU-8; UCS-2 har ikke ' t surrogater, bare almindelige kodepunkter, så de skal oversættes som sådan. Den virkelige fordel ved UTF-16 er, at det ' er lettere at opgradere en UCS-2-kodebase end en komplet omskrivning til UTF-8. Sjovt, hva?
- Sikker på, teknisk UTF-16 er ikke ' en superset af UCS-2, men hvornår var U + D800 til U + DFFF nogensinde brugt til alt andet end UTF-16 surrogater?
- Betyder ' ikke noget. Enhver anden behandling end blind passering gennem bytestream kræver, at du afkoder surrogatparene, som du kan ' ikke gøre, hvis du ' behandler det som UCS-2.
Svar
UTF-16 er bedste kompromis mellem håndtering og plads og derfor bruger de fleste større platforme (Win32, Java, .NET) det til intern repræsentation af strenge.
Kommentarer
- -1 fordi UTF-8 sandsynligvis vil være mindre eller ikke markant anderledes. For visse asiatiske scripts er UTF-8 tre byte pr. glyf, mens UTF-16 kun er to, men dette er afbalanceret af, at UTF-8 kun er en byte til ASCII (som ofte vises selv inden for asiatiske sprog i produktnavne, kommandoer og lignende). Yderligere, i de nævnte sprog, overfører en glyf mere information end en latinsk karakter, så det er berettiget for at det skal tage mere plads.
- Jeg kalder ikke at kombinere wor st sider af begge muligheder et godt kompromis.
- Det ' er ikke lettere end UTF-8. Det ' er også variabel længde.
- Efterlad debatter om fordelene ved UTF-16 til side: Det, du citerede, er ikke grund til Windows, Java eller .NET ved hjælp af UTF-16. Windows og Java går tilbage til et tidspunkt, hvor Unicode var en 16-bit-kodning. UCS-2 var et rimeligt valg dengang. Da Unicode blev en 21-bit-kodning, var migrering til UTF-16 det bedste valg, eksisterende platforme havde. Det havde intet at gøre med nem håndtering eller pladskompromisser. Det ' er kun et spørgsmål om arv.
- .NET arver Windows-arven her.
Svar
Jeg har aldrig forstået pointen med UTF-16. Hvis du vil have den mest pladseffektive repræsentation, skal du bruge UTF-8. Hvis du vil være i stand til at behandle tekst som fast længde, brug UTF-32. Hvis du ikke vil have nogen af dem, skal du bruge UTF-16. Værre endnu, da alle de almindelige (grundlæggende flersprogede plan) tegn i UTF-16 passer ind i et enkelt kodepunkt, bugs der antages at UTF-16 har fast længde vil være subtil og svær at finde, mens hvis du prøver at gøre dette med UTF-8, vil din kode mislykkes hurtigt og højt, så snart du prøver at internationalisere.
Svar
Da jeg endnu ikke kan kommentere, sender jeg dette som et svar, da det ser ud til, at jeg ellers ikke kan kontakte forfatterne af utf8everywhere.org
. Det er en skam, at jeg ikke automatisk får kommentarprivilegiet, da jeg har tilstrækkeligt ry på andre stackexchanges.
Dette menes som en kommentar til Udtalelse: Ja, UTF-16 skal betragtes som skadeligt svar.
En lille korrektion:
For at forhindre, at man ved et uheld sender en UTF-8 char*
til ANSI-strengversioner af Windows-API-funktioner, skal man definer UNICODE
, ikke _UNICODE
. _UNICODE
kortlægger funktioner som _tcslen
til wcslen
, ikke MessageBox
til MessageBoxW
. I stedet tager UNICODE
sig af sidstnævnte. Som bevis er dette fra MS Visual Studio 2005 “s WinUser.h
header:
#ifdef UNICODE #define MessageBox MessageBoxW #else #define MessageBox MessageBoxA #endif // !UNICODE
I det mindste, denne fejl skal rettes på utf8everywhere.org
.
Et forslag:
Måske skulle guiden indeholde et eksempel på eksplicit brug af Wide- strengversion af en datastruktur for at gøre det mindre let at gå glip af / glemme det.Brug af bredstrengede versioner af datastrukturer ud over brug af bredstrengede versioner af funktioner gør det endnu mindre sandsynligt, at man ved et uheld kalder en ANSI-strengversion af en sådan funktion.
Eksempel på eksempel:
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); }
Kommentarer
- Aftalt; tak! Vi opdaterer dokumentet. Dokumentet har stadig brug for mere udvikling og tilføjelse af oplysninger om databaser. Vi er glade for at modtage bidrag fra formuleringer.
- @PavelRadzivilovsky
_UNICODE
er der stadig 🙁 - tak for din påmindelse. Cubus, Jelle, Vil du have en bruger til vores SVN?
- @Pavel Sikker, vil sætte pris på det!
- @JelleGeerts: Jeg undskylder denne forsinkelse. Du kan altid kontakte os via vores e-mails (linket) fra manifestet) eller Facebook. Vi er lette at finde. Selvom jeg mener, at vi har løst det problem, du har bragt her (og jeg krediterede dig der), er hele UTF-8 vs UTF-16-debatterne stadig relevante. Hvis du har mere at gøre bidrager er du velkommen til at kontakte os gennem disse private kanaler.
Svar
Nogen sagde, at UCS4 og UTF-32 var Det samme. Nej, men jeg ved hvad du mener. En af dem koder dog for den anden. Jeg ville ønske, at de “tænkte at specificere endianness fra det første, så vi ikke ville have endianess-kampen udkæmpet her også. Kunne de ikke have set det komme? I det mindste er UTF-8 den samme overalt re (medmindre nogen følger den originale specifikation med 6 bytes).
Hvis du bruger UTF-16, skal du have til at medtage håndtering af multibyttegn. Du kan ikke gå til det Nte tegn ved at indeksere 2N i et byte-array. Du er nødt til at gå det eller have tegnindeks. Ellers har du skrevet en fejl.
Det aktuelle kladtspecifikation for C ++ siger at UTF-32 og UTF-16 kan have små endian-, big-endian- og uspecificerede varianter. Virkelig? Hvis Unicode havde specificeret, at alle skulle gøre lidt endian fra starten, ville det alle have været enklere. (Jeg ville også have haft det godt med big-endian.) I stedet implementerede nogle mennesker det på den ene måde, andre på den anden, og nu sidder vi fast med dumhed for ingenting. Nogle gange er det pinligt at være softwareingeniør.
Kommentarer
- Uspecificeret endianess antages at omfatte stykliste som det første tegn, der bruges til at bestemme, hvordan strengen skal læses. UCS-4 og UTF-32 er faktisk de samme i dag, dvs. en numerisk UCS-værdi mellem 0 og 0x10FFFF gemt i et 32-bit heltal.
- @Tronic: Teknisk set er dette ikke sandt. Selvom UCS-4 kan gemme ethvert 32-bit heltal, er UTF-32 forbudt at gemme de ikke-tegn-kodepunkter, der er ulovlige til udveksling, såsom 0xFFFF, 0xFFFE og alle surrogaterne. UTF er en transportkodning, ikke en intern.
- Endianness-problemer er uundgåelige, så længe forskellige processorer fortsætter med at bruge forskellige byteordrer. Det kunne dog have været rart, hvis der var en " foretrukket " byteordre til arkivering af UTF-16.
- Selvom UTF-32 er fast bredde for kodepunkter , er det ikke fast bredde for tegn . (Hørt om noget, der hedder ", der kombinerer tegn "?) Så du kan ' ikke gå til N ' det tegn simpelthen ved at indeksere 4N i byte-arrayet.
Svar
Jeg synes ikke, det er skadeligt, hvis udvikleren er forsigtig nok.
Og de bør acceptere denne afveje, hvis de også ved godt.
Som japansk softwareudvikler finder jeg UCS-2 stor nok, og begrænsning af pladsen forenkler tilsyneladende logikken og reducerer runtime-hukommelse, så det er godt nok at bruge utf-16 under UCS-2-begrænsning.
Der er et filsystem eller et andet program, der antager, at kodepunkter og byte er proportionale, så det rå kodepunktnummer kan garanteres at være passende til noget fast lager.
Et eksempel er NTFS og VFAT, der angiver UCS-2 som deres kodning af filnavne.
Hvis dette eksempel virkelig vil udvides til at understøtte UCS-4, kan jeg alligevel acceptere at bruge utf-8 til alt, men fast længde har gode punkter som:
- kan garanterer størrelsen efter længde (datastørrelse og codepoint-længde er proportional)
- kan bruge kodningsnummeret til hash-opslag
- ikke-komprimerede data har en rimelig størrelse (sammenlignet med utf-32 / UCS-4)
I fremtiden, når hukommelse / processorkraft er billig selv i alle indlejrede enheder, accepterer vi muligvis, at enheden er en smule langsom for ekstra cachemiss eller sidefejl og ekstra hukommelse brug, men dette sker ikke i den nærmeste fremtid antager jeg …
Kommentarer
- For dem, der læser denne kommentar, er det værd at bemærke, at UCS- 2 er ikke det samme som UTF-16. Se efter forskellene for at forstå.
Svar
“Skulle en af de mest populære kodninger, UTF-16, betragtes som skadelige? “
Meget muligvis, men alternativerne bør ikke nødvendigvis ses som værende meget bedre.
Det grundlæggende spørgsmål er, at der er mange forskellige begreber om: tegn, tegn, kodepunkter og bytesekvenser. Kortlægningen mellem hver af disse er ikke-triviel, selv ved hjælp af et normaliseringsbibliotek. (For eksempel er nogle tegn på europæiske sprog, der er skrevet med et latinbaseret script, ikke skrevet med et enkelt Unicode-kodepunkt. Og det er i den enklere ende af kompleksiteten!) Hvad dette betyder er, at det at få alting korrekt er ganske forbløffende vanskeligt; bizarre bugs kan forventes (og i stedet for kun at stønne om dem her, fortæl vedligeholdere for den pågældende software).
Den eneste måde, hvorpå UTF- 16 kan betragtes som skadelig i modsætning til f.eks. UTF-8 er, at den har en anden måde at kode kodepunkter uden for BMP (som et par surrogater). Hvis kode ønsker at få adgang til eller gentage ved hjælp af kodepunkt, det betyder, at det skal være opmærksom på forskellen. OTOH, det betyder, at en væsentlig del af eksisterende kode, der antager “tegn” altid kan passe ind i en to-byte mængde – en ret almindelig, hvis forkert, antagelse – kan ved fortsæt mindst med at arbejde uden at genopbygge det hele. Med andre ord, i det mindste kommer du til se den karakter s der ikke bliver håndteret rigtigt!
Jeg ville vende dit spørgsmål på hovedet og sige, at hele den forbandede shebang af Unicode skal betragtes som skadelig, og alle burde bruge en 8-bit-kodning, undtagen Jeg har set (i løbet af de sidste 20 år), hvor det fører: forfærdelig forvirring over de forskellige ISO 8859-kodninger plus hele sæt dem, der blev brugt til kyrillisk, og EBCDIC-pakken, og … ja, Unicode for alle dens fejl slår det . Hvis det kun var “ikke sådan et grimt kompromis mellem forskellige lande” misforståelser.
Kommentarer
- At kende vores held, om et par år ' Vi er ved at løbe tør for plads i UTF-16. Meh.
- Det grundlæggende spørgsmål er, at teksten er vildledende hård. Ingen tilgang til at repræsentere disse oplysninger på en digital måde kan være ukompliceret. Det ' er af samme grund, at datoer er hårde, kalendere er hårde, tid er hård, personlige navne er hårde, postadresser er hårde: når digitale maskiner krydser menneskelige kulturelle konstruktioner, kompleksitet bryder ud. Det er en kendsgerning i livet. Mennesker fungerer ikke på digital logik.