Bör UTF-16 betraktas som skadligt?

<åt sidan class = "s-notice s-notice__info js-post-notice mb16" role = "status">

Kommentarer

  • Inte riktigt korrekt. Jag förklarar, om du skriver " שָׁ " det sammansatta tecknet som består av " ש ", " ָ " och " ׁ ", vokaler, då är borttagning av var och en av dem logiskt, du tar bort en kodpunkt när du trycker på " backspace " och ta bort alla tecken inklusive vokaler när du trycker på " del ". Men du producerar aldrig olagligt tillstånd av text – olagliga kodpunkter. Situationen när du trycker på bakåt och får olaglig text är felaktig.
  • CiscoIPPhone: Om ett fel " rapporteras flera olika gånger, av många olika personer ", och sedan ett par år senare skriver en utvecklare på en dev-blogg att " Tro det eller ej, beteendet är mest avsiktligt! ", då (mildt sagt) brukar jag tro att det ' förmodligen inte är det bästa designbeslutet som någonsin gjorts. 🙂 Bara för att det ' s avsiktliga betyder inte ' t det ' är inte ett fel.
  • Bra inlägg. UTF-16 är verkligen " värsta av båda världarna ": UTF8 är variabel längd, täcker hela Unicode, kräver en transformationsalgoritm till och från råa kodpunkter, begränsas till ASCII, och det har inga problem med slutanvändning. UTF32 har fast längd, kräver ingen transformation, men tar mer utrymme och har problem med slutanvändning. Hittills så bra kan du använda UTF32 internt och UTF8 för serialisering. Men UTF16 har inga fördelar: Det är ' beroende av endian, det ' är variabel längd, det tar mycket utrymme, det ' är inte ASCII-kompatibelt. Den ansträngning som behövs för att hantera UTF16 ordentligt kan spenderas bättre på UTF8.
  • @Ian: UTF-8 INTE har samma förbehåll som UTF-8. Du kan inte ha surrogater i UTF-8. UTF-8 maskeras inte som något som det inte är, men de flesta programmerare som använder UTF-16 använder det fel. Jag vet. Jag ' har sett dem igen och igen och igen och igen.
  • Dessutom UTF-8 inte ' t har problemet eftersom alla behandlar det som en kodning med variabel bredd. Anledningen till att UTF-16 har problemet är att alla behandlar det som en kodning med fast bredd.

Svar

Detta är ett gammalt svar.
Se UTF-8 överallt för de senaste uppdateringarna.

Yttrande: Ja, UTF-16 bör betraktas som skadligt . Själva anledningen till att det existerar är för att det för en tid sedan tidigare fanns en missvisande tro på att widechar kommer att bli vad UCS-4 nu är.

Trots UTF-8s ”anglo-centrism” är det bör betraktas som den enda användbara kodningen för text. Man kan argumentera för att källkoder för program, webbsidor och XML-filer, OS-filnamn och andra dator-till-dator-textgränssnitt aldrig borde ha funnits. Men när de gör det är text inte bara för mänskliga läsare.

Å andra sidan är UTF-8 overhead ett litet pris att betala medan det har betydande fördelar. Fördelar som kompatibilitet med okunnig kod som bara skickar strängar med char*. Det här är en fantastisk sak. Det finns få användbara tecken som är kortare i UTF-16 än de är i UTF-8.

Jag tror att alla andra kodningar kommer att dö så småningom. Detta innebär att MS-Windows, Java, ICU, python sluta använda den som sin favorit. Efter lång forskning och diskussioner förbjuder utvecklingskonventionerna på mitt företag att använda UTF-16 var som helst utom OS API-samtal, och detta trots betydelse av prestanda i våra applikationer och det faktum att vi använder Windows. Konverteringsfunktioner utvecklades för att konvertera alltid antagen-UTF8 std::string s till native UTF-16, som Windows själv stöder inte ordentligt .

Till människor som säger ” använd vad som behövs där det behövs ”, säger jag: det är en stor fördel att använda samma kodning överallt, och jag ser ingen tillräcklig anledning att Speciellt tycker jag att lägga till wchar_t till C ++ var ett misstag, och så är Unicode-tilläggen till C ++ 0x. Vad som måste krävas av STL-implementeringar är dock att varje std::string eller char* -parametern anses vara unicode-kompatibel.

Jag är också emot ” användningen vad du vill ha ”tillvägagångssätt. Jag ser ingen anledning till sådan frihet. Det finns tillräckligt med förvirring om ämnet text, vilket resulterar i all denna trasiga programvara. Med detta sagt är jag övertygad om att programmerare äntligen måste nå enighet om UTF-8 som ett riktigt sätt. (Jag kommer från ett icke-ascii-talande land och växte upp på Windows, så jag skulle senast förväntas attackera UTF-16 baserat på religiösa grunder.) om hur jag gör text på Windows, och vad jag rekommenderar till alla andra för kompileringstiden kontrollerad unicode-korrekthet, användarvänlighet och bättre kodplattform. Förslaget skiljer sig väsentligt från vad som vanligtvis rekommenderas som det rätta sättet att använda Unicode på Windows. Ändå resulterade djupgående undersökningar av dessa rekommendationer i samma slutsats. Så här går:

  • Använd inte wchar_t eller std::wstring någon annanstans plats än intilliggande punkt till API: er som accepterar UTF-16.
  • Använd inte _T("") eller L"" UTF-16 bokstäver (Dessa bör IMO tas ur standarden , som en del av UTF-16 avskrivning).
  • Använd inte typer, funktioner eller deras derivat som är känsliga för _UNICODE konstant, såsom LPTSTR eller CreateWindow().
  • Ändå definieras _UNICODE alltid, till undvik att skicka char* strängar till WinAPI att bli tyst sammanställda
  • std::strings och char* var som helst i programmet betraktas som UTF-8 (om inte annat sägs)
  • Alla mina strängar är std::string, men du kan skicka char * eller sträng bokstavligt till convert(const std::string &).
  • använder bara Win32-funktioner som accepterar widechars (LPWSTR). Aldrig de som accepterar LPTSTR eller LPSTR. Skicka parametrar på detta sätt:

    ::SetWindowTextW(Utils::convert(someStdString or "string litteral").c_str()) 

    (Policyn använder konverteringsfunktioner nedan.)

  • Med MFC-strängar :

    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); 
  • Arbeta med filer, filnamn och fstream i Windows:

    • Skicka aldrig std::string eller const char* filnamnargument till fstream -familj. MSVC STL stöder inte UTF-8-argument, men har ett icke-standardtillägg som ska användas enligt följande:
    • Konvertera std::string argument till std::wstring med Utils::Convert:

      std::ifstream ifs(Utils::Convert("hello"), std::ios_base::in | std::ios_base::binary); 

      Vi måste manuellt ta bort konverteringen när MSVC: s inställning till fstream ändras.

    • Den här koden är inte flera plattformar och kan behöva ändras manuellt i framtiden
    • Se fstream unicode research / discussion case 4215 för mer info.
    • Skapa aldrig textutmatningsfiler med icke-UTF8-innehåll
    • Undvik att använda fopen() av RAII / OOD-skäl. Använd _wfopen() och WinAPI-konventionerna ovan.

// 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

  • Jag kan ' inte håller med. Fördelarna med utf16 jämfört med utf8 för många asiatiska språk dominerar helt de punkter du gör. Det är naivt att hoppas att japanerna, thailändarna, kineserna osv kommer att ge upp denna kodning. De problematiska sammanstötningarna mellan teckenuppsättningar är när teckenuppsättningarna mest liknar varandra, utom med skillnader. Jag föreslår att standardisera på: fast 7bit: iso-irv-170; 8bit-variabel: utf8; 16-bitars variabel: utf16; 32bit fast: ucs4.
  • @Charles: tack för din inmatning. Det är sant att vissa BMP-tecken är längre i UTF-8 än i UTF-16. Men låt oss ' inse det: problemet är inte i byte som kinesiska BMP-tecken tar, utan mjukvarudesignens komplexitet. Om en kinesisk programmerare ändå måste utforma för tecken med variabel längd, verkar det som om UTF-8 fortfarande är ett litet pris att betala jämfört med andra variabler i systemet. Han kan använda UTF-16 som en komprimeringsalgoritm om utrymmet är så viktigt, men även då kommer det inte att matchas för LZ, och efter LZ eller annan generisk komprimering tar båda ungefär samma storlek och entropi.
  • Vad jag i princip säger är att förenkling som erbjuds genom att ha En kodning som också är kompatibel med befintliga char * -program, och som också är den mest populära idag för allt är otänkbar.Det är nästan som i bra gamla " plaintext " dagar. Vill du öppna en fil med ett namn? Du behöver inte bry dig om vilken typ av unicode du gör osv. Jag föreslår att vi, utvecklare, begränsar UTF-16 till mycket speciella fall av allvarlig optimering där en liten bit av prestanda är värt att arbeta i månaden.
  • Linux har haft ett specifikt krav när man väljer att använda UTF-8 internt: kompatibilitet med Unix. Windows behövde inte ' det, och alltså när utvecklarna implementerade Unicode lade de till UCS-2-versioner av nästan alla funktioner som hanterade text och gjorde att multibyte helt enkelt konverterades till UCS-2 och ring de andra. De ersätter senare UCS-2 med UTF-16. Linux höll däremot på 8-bitars kodningar och använde därmed UTF-8, eftersom det ' är det rätta valet i så fall.
  • @Pavel Radzivilovsky : BTW, dina skrifter om " Jag tror att alla andra kodningar kommer att dö så småningom. Detta innebär att MS-Windows, Java, ICU, python slutar använda den som sin favorit. " och " I synnerhet tycker jag att lägga till wchar_t till C ++ var ett misstag, och så är unicode-tilläggen till C ++ Ox. " är antingen ganska naiva eller väldigt väldigt arroganta . Och detta kommer från någon som kodar hemma med en Linux och som är nöjd med UTF-8-tecken. För att uttrycka det direkt: Det vann ' t händer .

Svar

Unicode-kodpunkter är inte tecken! Ibland är de inte ens tecken (visuella former) .

Några exempel:

  • Romerska kodpunkter som ”ⅲ”. (En enstaka karaktär som ser ut som ”iii”.)
  • Tecken med accent som ”á”, som kan representeras som antingen ett enda kombinerat tecken ”\ u00e1” eller ett tecken och separerad diakritisk ”\ u0061 \ u0301 ”.
  • Tecken som grekiska små bokstäver sigma, som har olika former för mitten (” σ ”) och slutet (” ς ”) av ordpositioner, men som bör betraktas som synonymer för sökning.
  • Unicode diskretionär bindestreck U + 00AD, som kanske eller inte kan visas visuellt, beroende på sammanhang, och som ignoreras för semantisk sökning.

De enda sätten att få Unicode-redigering rätt är att använda ett bibliotek skrivet av en expert , eller bli expert och skriva ett själv. Om du bara räknar kodpunkter lever du i ett tillstånd av synd.

Kommentarer

  • Detta. Mycket detta. UTF-16 kan orsaka problem, men även om du använder UTF-32 genom hela kan (och kommer) det fortfarande ge dig problem.
  • Vad är en karaktär? Du kan definiera en kodpunkt som ett tecken och klara dig ganska bra. Om du menar en användarsynlig glyf, är det något annat.
  • @tchrist säker på att tilldela utrymme att definitionen är bra, men för något annat? Inte så mycket. Om du hanterar en kombinerande karaktär som ensam karaktär (dvs. för att radera eller " ta första N tecken " operation) du ' Jag får konstigt och fel beteende. Om en kodpunkt bara betyder när den kombineras med åtminstone en annan kan du ' t hantera den på egen hand på ett förnuftigt sätt.
  • @Pacerier, detta är sent till festen, men jag måste kommentera det. Vissa språk har mycket stora uppsättningar av potentiella kombinationer av diakritiker (se vietnamesiska, dvs. m i.e.t đừ). Att ha kombinationer snarare än ett tecken per diakrit är mycket användbart.
  • en liten anmärkning om terminologi: kodpunkter gör motsvarar unicode-tecken ; vad Daniel pratar om här är användarupplevda tecken , vilket motsvarar unicode-grafkluster

Svar

Det finns en enkel tumregel för vilken Unicode Transformation Form (UTF) som ska användas: – utf-8 för lagring och kommunikation – utf-16 för databehandling – du kan gå med utf-32 om det mesta av plattformens API du använder är utf-32 (vanligt i UNIX-världen).

De flesta system idag använder utf-16 (Windows, Mac OS, Java, .NET, ICU , Qt). Se även detta dokument: http://unicode.org/notes/tn12/

Tillbaka till ”UTF-16 som skadligt”, Jag skulle säga: definitivt inte.

Människor som är rädda för surrogater (tror att de förvandlar Unicode till en kodning med variabel längd) förstår inte de andra (mycket större) komplexiteterna som gör kartläggning mellan karaktärer och en Unicode-kodpunkt väldigt komplex: kombinerar tecken, ligaturer, variantväljare, kontrolltecken etc.

Läs bara den här serien här http://www.siao2.com/2009/06/29/9800913.aspx och se hur UTF-16 blir ett enkelt problem.

Kommentarer

  • Lägg till några exempel där UTF-32 är vanligt i UNIX-världen!
  • Nej, det gör du inte vill använda UTF-16 för databehandling. Det ' är en smärta i röven. Den har alla nackdelar med UTF-8 men ingen av dess fördelar. Både UTF-8 och UTF-32 är tydligt överlägsna det onda hacket som tidigare kallades fru UTF-16, vars efternamn var UCS-2. equalsIgnoreCase metod (även andra i strängklassen) som aldrig skulle ha varit där om Java hade använt antingen UTF-8 eller UTF-32. Det finns miljontals av dessa sovande bomber i vilken kod som helst som använder UTF-16, och jag är trött på dem. UTF-16 är en ond pox som plågar vår programvara med lömska buggar för alltid och alltid. Det är uppenbart skadligt och bör avskaffas och förbjudas.
  • @tchrist Wow så en icke-surrogatmedveten funktion (eftersom den skrevs när det inte fanns någon och är tyvärr dokumenterad på ett sådant sätt som gör det troligen omöjligt att anpassa – det anger .toUpperCase (char)) kommer att leda till fel beteende? Du ' är medveten om att en UTF-32-funktion med en föråldrad kodpunktskarta inte ' t hanterar detta bättre? Hela Java API hanterar inte surrogat särskilt bra och de mer invecklade punkterna om Unicode inte alls – och med senare skulle den använda kodningen inte alls '.
  • -1: En ovillkorlig .Substring(1) i .NET är ett trivialt exempel på något som bryter stöd för alla icke-BMP Unicode. Allt som använder UTF-16 har detta problem; det ' är för lätt att behandla det som en kodning med fast bredd och du ser problem för sällan. Det gör det till en aktivt skadlig kodning om du vill stödja Unicode.

Svar

Ja, absolut.

Varför? Det har att göra med utöva kod .

Om du tittar på dessa kodpunktsanvändningsstatistik i en stor grupp av Tom Christiansen ser du att trans-8bit BMP-kodpunkter används flera ordningar om storleken är större än icke-BMP-kodpunkter:

 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 

Ta TDD-dikten: ”Oprövad kod är trasig kod” och omformulera den som ”oövad kod är trasig kod”, och tänk hur ofta programmerare måste hantera icke-BMP-kodpunkter.

Fel relaterade till att inte hantera UTF-16 som kodning med variabel bredd är mycket mer benägna att gå obemärkt förbi än motsvarande buggar i UTF-8 . Vissa programmeringsspråk fortfarande garanterar inte att du ger UTF-16 istället för UCS-2, och vissa så kallade högnivåprogrammeringsspråk erbjuder åtkomst till kodenheter istället för kodpunkter (även C är tänkt att ge dig tillgång till kodpunkter om du använder wchar_t, oavsett vad någon plat formulär kan göra).

Kommentarer

  • " Fel relaterade till att inte hantera UTF-16 som en kodning med variabel bredd är mycket mer benägna att bli obemärkt än motsvarande buggar i UTF-8. " Detta är kärnan i frågan och därmed det rätta svaret.
  • Exakt. Om din UTF-8-hantering är borkad, är det ' omedelbart uppenbart. Om din UTF-8-hantering är borkad, kommer du ' bara märka om du lägger till ovanliga Han-tecken eller matematiska symboler.
  • Mycket sant, men å andra sidan hand, vad är enhetstester för om du borde lita på att hitta buggar i mindre frekventa fall?
  • @musiphil: när gjorde du senast ett enhetstest för icke-BMP-tecken?
  • För att utveckla mitt tidigare uttalande: även med UTF-8 kan du inte vara säker på att du har täckt alla fall efter att bara ha sett några exempel på arbete. Samma sak med UTF-16: du måste testa om din kod fungerar både med icke-surrogater och med surrogater. (Någon kan till och med hävda att UTF-8 har minst fyra huvudfall medan UTF-16 bara har två.)

Svar

Jag föreslår att tänkande UTF-16 kan anses vara skadligt säger att du måste få en större förståelse för unicode .

Eftersom jag har blivit nedröstad för att presentera min åsikt om en subjektiv fråga, låt mig utarbeta. Vad exakt är det som stör dig om UTF-16? Skulle du föredra om allt var kodat i UTF-8? UTF-7? Eller vad sägs om UCS-4? Naturligtvis är vissa applikationer inte utformade för att hantera enstaka teckenkoder där ute – men de är nödvändiga, särskilt i dagens globala informationsdomän, för kommunikation mellan internationella gränser.

Men egentligen, om du känner att UTF-16 bör betraktas som skadligt eftersom det är förvirrande eller kan implementeras på ett felaktigt sätt (unicode kan verkligen vara), vilken metod för teckenkodning skulle då kunna anses vara oskadlig?

EDIT: För att klargöra: Varför betrakta felaktiga implementeringar av en standard som en återspegling av själva standardens kvalitet? Som andra senare har noterat, bara för att en applikation använder ett verktyg felaktigt, betyder det inte att verktyget i sig är defekt. Om så vore fallet skulle vi förmodligen kunna säga saker som ”var nyckelord anses skadligt”, eller ”trådning anses vara skadligt”. Jag tror att frågan förväxlar standardens kvalitet och natur med de svårigheter som många programmerare har att implementera och använder det ordentligt, vilket jag känner beror mer på deras bristande förståelse för hur unicode fungerar, snarare än unicode i sig.

Kommentarer

  • -1: Vad sägs om att ta itu med några av Artyoms ' s objekt ons, snarare än att bara nedlåta honom?
  • BTW: När jag började skriva den här artikeln ville jag nästan skriva " Skulle Joel på Softeare-artikeln i Unicode övervägas skadligt " eftersom det finns många misstag. Till exempel: utf-8-kodning tar upp till 4 tecken och inte 6. Det skiljer inte heller mellan UCS-2 och UTF-16 som är riktigt olika – och orsakar faktiskt de problem jag pratar om.
  • Det bör också noteras att när Joel skrev den artikeln, var UTF-8-standarden WAS 6 byte, inte 4. RFC 3629 ändrade standarden till 4 byte flera månader EFTER att han skrev artikeln. Som mest på internet lönar det sig att läsa från mer än en källa och vara medveten om källornas ålder. Länken var inte ' t avsedd att vara " slutet alla vara alla " snarare en utgångspunkt.
  • Jag skulle se: utf-8 eller utf-32 som är: kodning av variabel längd i nästan alla fall (inklusive BMP) eller kodning av fast längd alltid.
  • @iconiK: Var inte dum. UTF-16 är absolut inte de facto -standarden för bearbetning av text. Visa mig en programmeringsspråk som är mer lämpad för textbehandling som Perl, som alltid har (ja, i mer än ett decennium) använde abstrakta tecken med en underliggande UTF-8-representation internt. På grund av detta hanterar varje Perl-program automatiskt alla Unicode utan att användaren ständigt behöver apa runt med idiotiska surrogat. Längden på en sträng är dess antal i kodpunkter, inte kodenheter. Allt annat är ren dumhet som sätter bakåt i bakåtkompatibilitet.

Svar

Det är inget fel med Utf- 16 kodning. Men språk som behandlar 16-bitarsenheterna som tecken bör antagligen betraktas som dåligt utformade. Att ha en typ som heter ”char” som inte alltid representerar en karaktär är ganska förvirrande. Eftersom de flesta utvecklare förväntar sig att en char-typ representerar en kodpunkt eller ett tecken kommer mycket kod troligen att gå sönder när de utsätts för tecken före BMP.

Observera att även att använda utf-32 inte betyder att varje 32- bitkodpunkt representerar alltid ett tecken. På grund av att kombinera tecken kan en faktisk karaktär bestå av flera kodpunkter. Unicode är aldrig trivialt.

BTW. Det finns förmodligen samma klass av buggar med plattformar och applikationer som förväntar sig att tecken ska vara 8-bitars, som matas med Utf-8.

Kommentarer

  • I Java ' fall, om du tittar på deras tidslinje ( java.com/en/javahistory/timeline.jsp), ser du att den främsta utvecklingen av String hände medan Unicode var 16 bitar (det ändrades 1996). De var tvungna att skruva på förmågan att hantera icke BMP-kodpunkter, därmed förvirringen.
  • @Kathy: Inte riktigt en ursäkt för C #, dock. Generellt håller jag med om att det ska finnas en CodePoint -typ med en enda kodpunkt (21 bitar), en CodeUnit -typ, som håller en enskild kodenhet (16 bitar för UTF-16) och en Character -typ skulle helst behöva stödja ett komplett grafem. Men det gör det funktionellt likvärdigt med ett String
  • Det här svaret är nästan två år gammalt, men jag kan ' t hjälp men kommentera det. " Att ha en typ med namnet ' char ' som inte alltid representerar en karaktär är vacker förvirrande. " Och ändå använder människor det hela tiden i C och liknande för att representera heltalsdata som kan lagras i en enda byte.
  • Och jag ' har sett ett parti av C-kod som inte ' t hanterar teckenkodning korrekt.
  • C # har en annan ursäkt: det var designat för Windows och Windows byggdes på UCS-2 (det ' är väldigt irriterande att även i dag kan Windows API inte stöd UTF-8). Dessutom tror jag att Microsoft ville ha Java-kompatibilitet (.NET 1.0 hade ett Java-kompatibilitetsbibliotek, men de tappade Java-stöd väldigt snabbt – jag ' gissar att detta beror på Sun ' s stämning mot MS?)

Svar

Mitt personliga val är att alltid använda UTF-8. Det är standarden på Linux för nästan allt. Den är bakåtkompatibel med många äldre appar. Det finns en mycket minimal kostnad när det gäller extra utrymme som används för icke-latinska tecken jämfört med andra UTF-format, och det finns betydande besparingar i utrymme för latinska tecken. På nätet är latinska språk härskande, och jag tror att de kommer att göra det under överskådlig framtid. Och för att ta itu med ett av huvudargumenten i det ursprungliga inlägget: nästan alla programmerare är medvetna om att UTF-8 ibland kommer att ha flerbyte-tecken i sig. Inte alla hanterar detta korrekt, men de är vanligtvis medvetna, vilket är mer än vad som kan sägas för UTF-16. Men naturligtvis måste du välja den som passar bäst för din ansökan. Det är därför det är mer än en i första hand.

Kommentarer

  • UTF-16 är enklare för allt inom BMP, att ' varför den används så mycket. Men jag ' är också ett fan av UTF-8, det har inga problem med byteordning, vilket fungerar till sin fördel.
  • Teoretiskt sett ja. I praktiken finns det saker som, säg, UTF-16BE, vilket betyder UTF-16 i stor endian utan BOM. Det här är inte något jag gjort, det här är en faktisk kodning tillåten i ID3v2.4-taggar (ID3v2-taggar suger, men är tyvärr allmänt använda). Och i sådana fall måste du definiera slutanvändning externt, eftersom själva texten inte innehåller '. UTF-8 skrivs alltid på ett sätt och det har inte ' ett sådant problem.
  • Nej, UTF-16 är inte enklare. Det är svårare. Det vilseleder och bedrar dig att tro att det är fast bredd. All sådan kod är trasig och allt eftersom du inte märker förrän det är för sent. FALL I PUNKT: Jag hittade just ännu ett dumt UTF-16-fel i Java-kärnbiblioteken igår, den här gången i String.equalsIgnoreCase, som lämnades i UCS-2 bakom buggery, och misslyckas därför på 16/17 giltiga Unicode-kodpunkter. Hur länge har den koden funnits? Ingen ursäkt för att det ska vara buggy. UTF-16 leder till ren dumhet och en olycka som väntar på att hända. Kör skrikande från UTF-16.
  • @tchrist Man måste vara en mycket okunnig utvecklare för att inte veta att UTF-16 inte har en fast längd. Om du börjar med Wikipedia kommer du att läsa följande högst upp: " Det ger ett resultat med variabel längd av antingen en eller två 16-bitars kodenheter per kodpunkt ". Vanliga frågor om Unicode säger samma sak: unicode.org/faq//utf_bom.html#utf16-1 . Jag vet inte ' hur UTF-16 kan lura någon om det står överallt att det är variabel längd. När det gäller metoden designades den aldrig för UTF-16 och bör inte ' inte betraktas som Unicode, så enkelt som det.
  • @tchrist Har du en källa för din statistik? Men om bra programmerare är knappa, tycker jag att det här är bra, för vi blir mer värdefulla. 🙂 När det gäller Java-API: erna kan char-baserade delar så småningom upphöra att gälla, men detta är inte en garanti för att de inte kommer att användas '. Och de kommer definitivt inte att ta bort ' av kompabilitetsskäl.

Svar

Det finns en kodning som använder symboler i fast storlek. Jag menar verkligen UTF-32. Men fyra byte för varje symbol är för mycket slösat utrymme, varför skulle vi använda det i vardagliga situationer?

Enligt min mening framgår de flesta problemen av det faktum att en del program föll bakom Unicode-standarden, men var inte snabba att korrigera situationen. Opera, Windows, Python, Qt – alla dök upp innan UTF-16 blev allmänt känd eller till och med uppstod. Jag kan dock bekräfta att i Opera, Windows Explorer och Notepad finns det inga problem med tecken utanför BMP längre (åtminstone på min dator). Men hur som helst, om program inte känner igen surrogatpar, använder de inte UTF-16. Oavsett vilka problem som uppstår vid hantering av sådana program har de inget att göra med själva UTF-16.

Men jag tror att problemen med äldre programvara med endast BMP-stöd är något överdrivna. Tecken utanför BMP påträffas endast i mycket specifika fall och områden. Enligt Officiella vanliga frågor om Unicode , ”även i östasiatisk text bör förekomsten av surrogatpar vara i genomsnitt mindre än 1% av all textlagring”.Naturligtvis bör karaktärer utanför BMP inte försummas eftersom ett program inte är Unicode-överensstämmande annars, men de flesta program är inte avsedda att arbeta med texter som innehåller sådana tecken. Det är därför om de inte gör det t stödja det, det är obehagligt, men inte en katastrof.

Låt oss nu överväga alternativet. Om UTF-16 inte fanns, skulle vi inte ha en kodning som är väl lämpad för icke-ASCII-text, och all programvara som skapats för UCS-2 måste omformas helt för att förbli Unicode-kompatibel. Det senare skulle sannolikt bara sakta ner Unicode-antagandet. Vi skulle inte heller ha kunnat upprätthålla kompatibilitet med text i UCS-2 som UTF-8 gör i förhållande till ASCII.

Nu, när man lägger till alla äldre frågor, vad är argumenten mot kodningen Jag tvivlar verkligen på att utvecklare nuförtiden inte vet att UTF-16 är variabel längd, det är skrivet överallt med Wikipedia. UTF-16 är mycket mindre svårt att analysera än UTF-8, om någon påpekade komplexitet som ett möjligt problem. Det är också fel att tro att det är enkelt att röra sig med att bestämma stränglängden endast i UTF-16. Om du använder UTF-8 eller UTF-32, bör du fortfarande vara medveten om att en Unicode-kodpunkt inte nödvändigtvis betyder ett tecken. Förutom det tror jag inte att det finns något väsentligt mot kodningen.

Därför tycker jag inte att själva kodningen ska betraktas som skadlig. UTF-16 är en kompromiss mellan enkelhet och kompakthet, och det finns ingen skada i att använda det som behövs där det behövs I vissa fall måste du förbli kompatibel med ASCII och du behöver UTF-8, i vissa fall vill du arbeta med att arbeta med Han-ideografier och spara utrymme med UTF-16, i vissa fall behöver du universella representationer av tecken som använder en fast -längdskodning. Använd det som är mer lämpligt, gör det bara ordentligt.

Kommentarer

  • Att ' är en ganska blinkad, anglo-centrerad vy, Malcolm. Nästan i nivå med " ASCII är tillräckligt bra för USA – resten av världen borde passa in i oss ".
  • Egentligen ' kommer från Ryssland och stöter på kyrilliker hela tiden (inklusive mina egna program), så jag don ' Jag tror inte att jag har en angocentrisk syn. 🙂 Att nämna ASCII är inte riktigt lämpligt, eftersom det ' inte är Unicode och inte ' t stöder specifika tecken. UTF-8, UTF-16, UTF-32 stöder samma internationella teckenuppsättningar, de är bara avsedda att användas i sina specifika områden. Och det här är precis min poäng: om du använder mestadels engelska, använd UTF-8, om du använder mest kyrilliker, använd UTF-16, om du använder gamla språk, använd UTF-32. Ganska enkelt.
  • " Inte sant, asiatiska manus som japanska, kinesiska eller arabiska tillhör också BMP. BMP i sig är faktiskt väldigt stort och säkert tillräckligt stort för att inkludera alla skript som används idag " Det här är allt så fel. BMP innehåller 0xFFFF-tecken (65536). Kinesiska ensamma har mer än så. Kinesiska standarder (GB 18030) har mer än så. Unicode 5.1 tilldelade redan mer än 100 000 tecken.
  • @Marcolm: " Själva BMP är faktiskt väldigt stort och säkert tillräckligt stort för att inkludera alla skript som används idag " Inte sant. Vid denna tidpunkt har Unicode redan tilldelat cirka 100 000 tecken, mycket mer än BMP kan passa. Det finns stora bitar av kinesiska tecken utanför BMP. Och vissa av dem krävs enligt GB-18030 (obligatorisk kinesisk standard). Annat krävs enligt (icke-obligatoriska) japanska och koreanska standarder. Så om du försöker sälja något på dessa marknader behöver du bortom BMP-stöd.
  • Allt som använder UTF-16 men bara kan hantera smala BMP-tecken använder faktiskt inte UTF-16. Det är buggy och trasigt. Utgångspunkten för OP är sund: UTF-16 är skadligt eftersom det leder till att ï har skrivit trasig kod. Antingen kan du hantera Unicode-text eller så kan du inte. Om du inte kan välja en delmängd som är lika dum som ASCII-textbehandling.

Svar

År av Windows-internationaliseringsarbete, särskilt i östasiatiska språk, kan ha skadat mig, men jag lutar mig mot UTF-16 för intern-till-programmet-representationer av strängar och UTF-8 för nätverks- eller fillagring av vanlig som dokument. UTF-16 kan dock vanligtvis bearbetas snabbare i Windows, så det är den främsta fördelen med att använda UTF-16 i Windows.

Att göra språnget till UTF-16 förbättrade dramatiskt tillräckligheten för genomsnittlig produkthantering internationell text.Det finns bara ett fåtal smala fall när surrogatparet måste övervägas (raderingar, insättningar och linjebrytande, i grund och botten) och medelfallet är oftast rakt genom. Och till skillnad från tidigare kodningar som JIS-varianter, begränsar UTF-16 surrogatpar till ett mycket smalt intervall, så kontrollen är väldigt snabb och fungerar framåt och bakåt.

Beviljas, det är ungefär lika snabbt i korrekt- kodad UTF-8 också. Men det finns också många trasiga UTF-8-applikationer som felaktigt kodar surrogatpar som två UTF-8-sekvenser. Så UTF-8 garanterar inte heller frälsning.

IE hanterar surrogatpar ganska bra sedan 2000 eller så, även om det vanligtvis omvandlar dem från UTF-8-sidor till en intern UTF-16-representation; I ”Jag är ganska säker på att Firefox också har det rätt, så jag bryr mig inte riktigt vad Opera gör.

UTF-32 (även kallad UCS4) är meningslöst för de flesta applikationer eftersom det är så utrymmeskrävande, så det är ganska mycket en nonstarter.

Kommentarer

  • Jag fick inte ' inte riktigt kommentera UTF-8 och surrogatpar. Surrogatpar är bara ett begrepp som är meningsfullt i UTF-16-kodningen, eller hur? Kod som konverteras direkt från UTF-16-kodning till UTF-8-kodning kan få det fel, och i det i fallet är problemet felaktigt att läsa UTF-16, inte skriva UTF-8. Är det rätt?
  • Vad Jason ' talar om är programvara som implementerar medvetet UTF-8 på det sättet: skapa ett surrogatpar, sedan UTF-8 en kod varje halvdel separat. Det korrekta namnet för den kodningen är CESU-8, men Oracle (t.ex.) felaktigt framställer det som UTF-8. Java använder ett liknande system för objektserialisering, men det ' är tydligt dokumenterat som " Modifierad UTF-8 " och endast för internt bruk. (Om vi bara kunde få folk att LÄSA den dokumentationen och sluta använda DataInputStream # readUTF () och DataOutputStream # writeUTF () på ett olämpligt sätt …)
  • AFAIK, UTF-32 är fortfarande kodning med variabel längd, och inte lika med UCS4, vilket är specifikt kodpunktsintervall.
  • @Eonil, UTF-32 kommer alltid att kunna särskiljas från UCS4 om vi har en Unicode-standard som har ungefär en UCS5 eller större.
  • @JasonTrue Ändå är bara resultaten lika lika, inte garanterat av design. Samma sak hände i 32-bitars minnesadressering, Y2K, UTF16 / UCS2. Eller har vi någon garanti för denna jämlikhet? Om vi har det skulle jag gärna använda det. Men jag vill ' inte skriva en möjlig brytbar kod. Jag skriver en karaktärsnivåkod och bristen på ett garanterat sätt att koda om mellan UTF < – > kodpunkten buggar mig mycket .

Svar

UTF-8 är definitivt vägen att gå, eventuellt åtföljd av UTF-32 för intern användning i algoritmer som behöver slumpmässig åtkomst med hög prestanda (men som ignorerar att kombinera tecken).

Både UTF-16 och UTF-32 (liksom deras LE / BE-varianter) lider av problem med slutanfallet, så de borde använd aldrig externt.

Kommentarer

  • Slumpmässig åtkomst med konstant tid är också möjlig med UTF-8, använd bara kodenheter snarare än kodpunkter. Kanske behöver du riktig slumpmässig kodpunktåtkomst, men jag ' har aldrig sett ett användningsfall och du ' är lika sannolikt att du vill slumpmässigt grafemklusteråtkomst istället.

Svar

UTF-16? definitivt skadligt. Bara mitt saltkorn här, men det finns exakt tre acceptabla kodningar för text i ett program:

  • ASCII: när man hanterar saker på låg nivå (t.ex. mikrokontroller) som inte har råd med något bättre
  • UTF8: lagring i media med fast bredd såsom filer
  • heltalskodpunkter (”CP”?): en matris med de största heltal som är lämpliga för ditt programmeringsspråk och plattform (förfaller till ASCII i gränsen för låga resorces). Bör vara int32 på äldre datorer och int64 på vad som helst med 64-bitars adressering.

  • Uppenbarligen gränssnitt till äldre kodanvändning vilken kodning som behövs för att den gamla koden ska fungera.

Kommentarer

  • @simon buchan, U+10ffff max går ut genom fönstret när (inte om) de tar slut på kodpunkter. Som sagt, att använda int32 på ett p64-system för hastighet är förmodligen säkert, eftersom jag tvivlar på att de ' kommer att överstiga U+ffffffff innan du tvingas skriva om din kod för 128-bitars system runt 2050. (Det är poängen med " använd det största intet som är bekvämt " i motsats till " största tillgängliga " (vilket förmodligen skulle vara int256 eller bignums eller något).)
  • @ David: Unicode 5.2 kodar 107 361 kodpunkter.Det finns 867 169 oanvända kodpunkter. " när " bara är dumt. En Unicode-kodpunkt definieras som ett tal från 0 till 0x10FFFF, en egenskap som UTF-16 är beroende av. (2050 verkar också vara mycket lågt uppskattat för 128-bitars system när ett 64-bitars system kan hålla hela Internet i det ' s adressutrymme.)
  • @David: Din " när " hänvisade till att Unicode-kodpunkterna hade slut, inte en 128-bitars switch som ja kommer att vara under de närmaste århundradena. Till skillnad från minne finns det ingen exponentiell tillväxt av tecken, så Unicode Consortium har specifikt garanterat att de aldrig tilldelar en kodpunkt över U+10FFFF. Detta är verkligen en av de situationer när 21 bitar räcker för någon.
  • @Simon Buchan: Åtminstone fram till första kontakten. 🙂
  • Unicode används för att garantera att det inte finns några kodpunkter över U + FFFF också.

Svar

Unicode definierar kodpunkter upp till 0x10FFFF (1114,112 koder), alla applikationer som körs i flerspråkig miljö med strängar / filnamn etc. ska hantera det korrekt.

Utf-16 : täcker endast 1.112.064 koder. Även om de i slutet av Unicode kommer från plan 15-16 (privat användningsområde). Det kan inte växa längre i framtiden förutom att bryta Utf-16 koncept.

Utf-8 : täcker teoretiskt 2 216 757 376 koder. Nuvarande intervall för Unicode -koder kan representeras av maximalt 4 bytesekvenser. Det lider inte med byteordning problem, det är ”kompatibelt” med ascii.

Utf-32 : täcker teoretiskt 2 ^ 32 = 4 294 967 296 koder. För närvarande är den inte kodad med variabel längd och kommer troligen inte att vara i framtiden.

Dessa fakta är självförklarande. Jag förstår inte att förespråka allmän användning av Utf-16 . Det är kodat med variabel längd (kan inte nås via index), det har problem att täcka hela Unicode även för närvarande, byteorder måste hanteras, etc. Jag ser ingen fördel förutom att den används inbyggt i Windows och vissa andra platser. Även om det är förmodligen bättre att använda Utf-8 när du skriver flera plattformskoder och göra omvandlingar endast vid slutpunkterna på plattformsberoende sätt (som redan föreslagits). När direkt åtkomst via index är nödvändigt och minnet inte är ett problem ska Utf-32 användas.

Huvudproblemet är att många programmerare som hanterar Windows Unicode = Utf-16 inte ens vet eller ignorerar det faktum att det är kodat med variabel längd.

Så som det vanligtvis är i * nix plattform är ganska bra, c-strängar (char *) tolkas som Utf-8 kodade, breda c-strängar (wchar_t *) tolkas som Utf-32 .

Kommentarer

  • Obs: UTF -16 täcker All Unicode då Unicode Consortium bestämde att 10FFFF är TOP-intervallet för Unicode och definierade UTF-8 maximal 4 bytes längd och uttryckligen uteslutet intervall 0xD800-0xDFFF från giltigt kodpunktsintervall och detta intervall används för att skapa surrogat par. Så vilken giltig Unicode-text som helst kan representeras med var och en av dessa kodningar. Också om att växa till framtiden. Det verkar inte ' t att 1 miljon kodpunkter inte skulle räcka i någon längre framtid.
  • @Kerrek: Fel: UCS-2 är inte en giltig Unicode kodning. Alla UTF- * -kodningar kan per definition representera alla Unicode-kodpunkter som är lagliga för utbyte. UCS-2 kan representera mycket färre än så, plus några fler. Upprepa: UCS-2 är inte en giltig Unicode-kodning, något mer än ASCII är.
  • " Jag förstår inte att förespråka allmän användning av Utf- 8 . Den är kodad med variabel längd (kan inte nås via index) "
  • @Ian Boyd, behovet av att komma åt en strängs individuella karaktär i ett slumpmässigt åtkomstmönster är otroligt överdriven. Det är ungefär lika vanligt som att vilja beräkna diagonalen för en matris av tecken, vilket är super ovanligt. Strängar bearbetas praktiskt taget alltid sekventiellt, och eftersom åtkomst till UTF-8-karaktär N + 1 med tanke på att du är på UTF-8-karaktär N är O (1), finns det inget problem. Det finns överlägset lite behov av att göra slumpmässig åtkomst till strängar. Oavsett om du tycker att det är värt lagringsutrymmet att gå till UTF-32 istället för UTF-8 är din egen åsikt, men för mig är det helt en sak.
  • @tchrist, jag ger dina strängar bearbetas praktiskt taget alltid sekventiellt om du inkluderar omvänd iteration som " sekventiell " och sträcker det lite ytterligare jämförelse av den bakre änden av en sträng till en känd sträng. Två mycket vanliga scenarier är trunkering av mellanslag från slutet av strängar och kontroll av filtillägget i slutet av en sökväg.

Svar

Lägg till detta i listan:

Det presenterade scenariot är enkelt (ännu enklare eftersom jag kommer att presentera det här än det var ursprungligen! ): 1.En WinForms TextBox sitter på ett formulär, tomt. Den har en MaxLängd inställd på 20 .

2. Användaren skriver in TextBox, eller kanske klistrar in text i den.

3. Oavsett vad du skriver eller klistrar in i TextBoxen är du begränsad till 20, men det kommer sympatiskt att pipa vid text bortom 20 (YMMV här; jag ändrade mitt ljudschema för att ge mig den effekten!).

4. Det lilla paketet text skickas sedan någon annanstans för att starta ett spännande äventyr.

Nu är detta ett enkelt scenario, och vem som helst kan skriva upp detta på sin fritid. Jag skrev bara upp det själv på flera programmeringsspråk med WinForms, för jag var uttråkad och hade aldrig provat det förut. Och med text på flera faktiska språk eftersom jag är ansluten på det sättet och har fler tangentbordslayouter än möjligen någon i hela det freaking universum.

Jag heter till och med formuläret Magic Carpet Ride för att hjälpa till att förbättra tristess.

Detta fungerade inte, för vad det är värt.

Så istället skrev jag in följande 20 tecken i min Magic Carpet Ride form:

0123401234012340123 𠀀

Uh oh.

Det sista tecknet är U + 20000, det första Tillägg B-ideografi för Unicode (aka U + d840 U + dc00, till sina nära vänner som han inte skäms för att bli avlägsnad, som det var, framför) ….

ange bildbeskrivning här

Och nu har vi ett bollspel.

För när TextBox. MaxLength talar om

Hämtar eller ställer in det maximala antalet tecken som kan matas in manuellt i textrutan.

vad det egentligen betyder är

Gets or sets maximalt antal UTF-16 LE-torsk enheter som manuellt kan matas in i textrutan och kommer att nådeslöst trunka den levande skiten ur alla strängar som försöker spela sötnosiga spel med den språkliga karaktärsföreställningen att bara någon som är så besatt som den Kaplan-karlen kommer att finna stötande få ut mer!).

Jag försöker se om hur dokumentet uppdateras ….
Vanliga läsare som kom ihåg att min UCS-2 till UTF-16 serien kommer att notera min olycklighet med det förenklade begreppet TextBox.MaxLength och hur den ska hantera åtminstone detta fall där dess drakoniska beteende skapar en olaglig sekvens, en som andra delar av .Net Framework kan kasta ett

  • System.Text.EncoderFallbackException : Det gick inte att översätta Unicode-tecknet \ uD850 vid index 0 till angiven kodsida. *

undantag om du skickar denna sträng någon annanstans i .Net Framework (som min kollega Dan Thompson gjorde).

Nu okej, kanske UCS-2 till UTF-16-serien är utom räckhåll för många.
Men är inte ”t är det rimligt att förvänta sig att TextBox.Text inte kommer att producera ett System.String som inte kommer att få en annan del av .Net Framework att kasta? Jag menar, det är inte som att det finns en chans i form av någon händelse på kontrollen som berättar om den kommande trunkeringen där du enkelt kan lägga till en smartare validering – validering som själva kontrollen inte har något emot. gå så långt som att säga att denna punk-kontroll bryter ett säkerhetskontrakt som till och med kan leda till säkerhetsproblem om du kan klassera och orsaka oväntade undantag för att avsluta en applikation som en grov typ av förnekelse av tjänst. Varför skulle någon WinForms-process eller -metod eller algoritm eller teknik ger ogiltiga resultat?

Källa: Michael S.Kaplan MSDN-blogg

Kommentarer

  • Tack, mycket bra länk! Jag ' har lagt till den i problemlistan i frågan.

Svar

Jag skulle inte nödvändigtvis säga att UTF-16 är skadligt. Det är inte elegant, men det tjänar sitt syfte att bakåtkompatibilitet med UCS-2, precis som GB18030 gör med GB2312, och UTF-8 gör med ASCII.

Men att göra en grundläggande förändring av Unicodes struktur i mellanströmmen, efter att Microsoft och Sun hade byggt enorma API: er runt 16-bitars tecken, var skadligt. Misslyckandet med att sprida medvetenheten om förändringen var mer skadlig.

Kommentarer

  • UTF-8 är ett övermängd av ASCII , men UTF-16 är INTE ett superset av UCS-2. Även om det nästan är en superset, resulterar en korrekt kodning av UCS-2 i UTF-8 i avsky som kallas CESU-8; UCS-2 har inte ' t surrogat, bara vanliga kodpunkter, så de måste översättas som sådana. Den verkliga fördelen med UTF-16 är att det ' är lättare att uppgradera en UCS-2-kodbas än en fullständig omskrivning för UTF-8. Roligt, va?
  • Visst, tekniskt UTF-16 är inte ' en superset av UCS-2, men när var U + D800 till U + DFFF någonsin används för allt utom UTF-16 surrogater?
  • Spelar ingen roll '. Annan bearbetning än att blint passera genom bytestream kräver att du avkodar surrogatparet, som du kan ' t göra om du ' behandlar det som UCS-2.

Svar

UTF-16 är bästa kompromiss mellan hantering och utrymme och därför använder de flesta större plattformar (Win32, Java, .NET) den för intern representation av strängar.

Kommentarer

  • -1 eftersom UTF-8 sannolikt är mindre eller inte signifikant annorlunda. För vissa asiatiska skript är UTF-8 tre byte per glyf medan UTF-16 bara är två, men detta är balanserad av att UTF-8 bara är en byte för ASCII (som ofta förekommer även inom asiatiska språk i produktnamn, kommandon och sådana saker). Vidare, på de nämnda språken, överför en glyf mer information än en latinsk karaktär så det är motiverat för att det ska ta mer plats.
  • Jag skulle inte kalla att kombinera wor båda sidorna av båda alternativen en bra kompromiss.
  • Det ' är inte enklare än UTF-8. Det är ' också med variabel längd.
  • Att lämna debatter om fördelarna med UTF-16 åt sidan: Vad du citerade är inte anledning till att Windows, Java eller .NET använder UTF-16. Windows och Java går tillbaka till en tid då Unicode var en 16-bitars kodning. UCS-2 var ett rimligt val då. När Unicode blev en 21-bitars kodning var migrering till UTF-16 det bästa valet som befintliga plattformar hade. Det hade ingenting att göra med enkel hantering eller rymdkompromisser. Det ' är bara en fråga om äldre.
  • .NET ärver Windows-arvet här.

Svar

Jag har aldrig förstått poängen med UTF-16. Om du vill ha den mest rymdeffektiva representationen, använd UTF-8. Om du vill kunna behandla text som fast längd, använd UTF-32. Om du inte vill ha något, använd UTF-16. Ännu värre, eftersom alla vanliga (grundläggande flerspråkiga plan) tecken i UTF-16 passar i en enda kodpunkt, buggar att UTF-16 har fast längd kommer att vara subtilt och svårt att hitta, medan om du försöker göra detta med UTF-8 kommer din kod att misslyckas snabbt och högt så snart du försöker internationalisera.

Svar

Eftersom jag ännu inte kan kommentera lägger jag upp detta som ett svar, eftersom det verkar som att jag annars inte kan kontakta författarna till utf8everywhere.org. Det är synd att jag inte automatiskt får kommentarprivilegiet, eftersom jag har tillräckligt med rykte på andra stackexchanges.

Detta menas som en kommentar till Yttrande: Ja, UTF-16 bör betraktas som skadligt svar.

En liten korrigering:

För att förhindra att man av misstag skickar en UTF-8 char* till versioner av ANSI-strängar av Windows-API-funktioner bör man definiera UNICODE, inte _UNICODE. _UNICODE mappar funktioner som _tcslen till wcslen, inte MessageBox till MessageBoxW. Istället tar UNICODE definieringen hand om den senare. För bevis är detta från MS Visual Studio 2005 ”s WinUser.h header:

#ifdef UNICODE #define MessageBox MessageBoxW #else #define MessageBox MessageBoxA #endif // !UNICODE 

I det minsta, detta fel bör korrigeras på utf8everywhere.org.

Ett förslag:

Kanske bör guiden innehålla ett exempel på uttrycklig användning av Wide- strängversion av en datastruktur, för att göra det mindre lätt att missa / glömma det.Att använda bredsträngsversioner av datastrukturer utöver att använda bredsträngsversioner av funktioner gör det ännu mindre troligt att man av misstag anropar en ANSI-strängversion av en sådan funktion.

Exempel på exempel:

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

  • Överenskomna; tack! Vi kommer att uppdatera dokumentet. Dokumentet behöver fortfarande mer utveckling och lägga till information om databaser. Vi är glada att få bidrag från formuleringar.
  • @PavelRadzivilovsky _UNICODE är fortfarande kvar 🙁
  • tack för påminnelsen. Cubus, Jelle, Vill du ha en användare till vårt SVN?
  • @Pavel Visst, skulle uppskatta det!
  • @JelleGeerts: Jag ber om ursäkt för denna försening. Du kan alltid kontakta oss via våra e-postmeddelanden (länkade) från manifestet) eller Facebook. Vi är lätta att hitta. Även om jag tror att vi har fixat problemet du tog med här (och jag krediterade dig där) är hela UTF-8 vs UTF-16-debatterna fortfarande relevanta. Om du har mer att göra bidra gärna till att kontakta oss via dessa privata kanaler.

Svar

Någon sa att UCS4 och UTF-32 var samma. Nej så, men jag vet vad du menar. En av dem är en kodning av den andra, dock. Jag önskar att de ”tänkte specificera slutgiltighet från det första så att vi inte skulle utkämpa endianessstrid här också. Kunde inte de ha sett det komma? Åtminstone är UTF-8 samma för alla re (såvida inte någon följer den ursprungliga specifikationen med 6 byte).

Om du använder UTF-16 måste du ha att inkludera hantering av multibyt-tecken. Du kan inte gå till N: t tecken genom att indexera 2N i en byte-array. Du måste gå det eller ha teckenindex. Annars har du skrivit ett fel.

Det nuvarande utkastspecifikationen för C ++ säger att UTF-32 och UTF-16 kan ha små endian-, big-endian- och ospecificerade varianter. Verkligen? Om Unicode hade specificerat att alla var tvungna att göra lite-endian från början så hade allt varit enklare. (Jag skulle ha varit bra med big-endian också.) Istället implementerade vissa det på ett sätt, andra det andra, och nu sitter vi fast med dumhet för ingenting. Ibland är det pinsamt att vara mjukvaruutvecklare.

Kommentarer

  • Ospecificerad endianess ska inkludera BOM som det första tecknet, som används för att bestämma hur strängen ska läsas. UCS-4 och UTF-32 är faktiskt desamma idag, dvs. ett numeriskt UCS-värde mellan 0 och 0x10FFFF lagrat i ett 32-bitars heltal.
  • @Tronic: Tekniskt sett är detta inte sant. Även om UCS-4 kan lagra vilket 32-bitars heltal som helst, är UTF-32 förbjudet att lagra de kodpunkter som inte är tecken som är olagliga för utbyte, till exempel 0xFFFF, 0xFFFE och alla surrogater. UTF är en transportkodning, inte en intern.
  • Endiannessproblem är oundvikliga så länge som olika processorer fortsätter att använda olika bytebeställningar. Det kan dock ha varit trevligt om det fanns en " föredragen " byteordning för fillagring av UTF-16.
  • Även om UTF-32 är fast bredd för kodpunkter , är det inte fast bredd för tecken . (Hört av något som heter " som kombinerar tecken "?) Så du kan ' t gå till N ' det tecknet helt enkelt genom att indexera 4N i byte-arrayen.

Svara

Jag tycker inte att det är skadligt om utvecklaren är noggrann.
Och de bör acceptera denna avvägning om de också vet väl.

Som japansk mjukvaruutvecklare tycker jag att UCS-2 är tillräckligt stor och att begränsa utrymmet förenklar uppenbarligen logiken och minskar körningsminnet, så att använda utf-16 under UCS-2-begränsning är tillräckligt bra.

Det finns filsystem eller andra applikationer som antar att kodpunkter och byte är proportionella, så att rå kodpunktnummer kan garanteras att passa till en viss lagring i fast storlek.

Ett exempel är NTFS och VFAT som anger UCS-2 som deras kodning av filnamn.

Om det här exemplet verkligen vill utvidgas till att stödja UCS-4, kan jag gå med på att använda utf-8 för allt hur som helst, men fast längd har bra poäng som:

  1. kan garantera storleken efter längd (datastorlek och kodpunktens längd är proportionell)
  2. kan använda kodningsnumret för hash-sökning
  3. icke-komprimerad data är rimligt stor (jämfört med utf-32 / UCS-4)

I framtiden när minne / processorkraft är billig även i alla inbäddade enheter kan vi acceptera att enheten är lite långsam för extra cachemissar eller sidfel och extra minne användning, men detta kommer inte att ske inom en snar framtid antar jag …

Kommentarer

  • För de som läser den här kommentaren är det värt att notera att UCS- 2 är inte samma sak som UTF-16. Vänligen leta upp skillnaderna för att förstå.

Svar

”Skulle en av de mest populära kodningar, UTF-16, anses vara skadliga? ”

Ganska möjligen, men alternativen bör inte nödvändigtvis ses som mycket bättre.

Den grundläggande frågan är att det finns många olika begrepp om: tecken, tecken, kodpunkter och bytesekvenser. Kartläggningen mellan var och en av dessa är inte trivial, även med hjälp av ett normaliseringsbibliotek. (Till exempel är vissa tecken på europeiska språk som är skrivna med ett latinbaserat manus inte skrivna med en enda Unicode-kodpunkt. Och det är i den enklare änden av komplexiteten!) Vad detta betyder är att för att få allt rätt är ganska otroligt svårt; bisarra buggar kan förväntas (och i stället för att bara klaga om dem här, berätta för underhållarna för den aktuella programvaran).

Det enda sättet på vilket UTF- 16 kan anses vara skadligt i motsats till, säg, UTF-8 är att den har ett annat sätt att koda kodpunkter utanför BMP (som ett par surrogat). Om kod vill komma åt eller itera genom kodpunkt, det betyder att det måste vara medveten om skillnaden. OTOH, det betyder att en betydande del av befintlig kod som antar ”tecken” alltid kan passa in i en två-byte kvantitet – ett ganska vanligt, om fel, antagande – kan vid fortsätt åtminstone att arbeta utan att bygga om allt. Med andra ord, åtminstone kommer du till se den karaktären s som inte hanteras rätt!

Jag skulle vända din fråga på huvudet och säga att hela jävla shebangen i Unicode bör anses skadlig och alla borde använda en 8-bitars kodning, förutom Jag har sett (under de senaste 20 åren) vart det leder: hemsk förvirring över de olika ISO 8859-kodningarna, plus hela uppsättningen av de som används för kyrilliska och EBCDIC-sviten, och … ja, Unicode för alla dess fel slår det . Om det bara inte var en sådan otäck kompromiss mellan olika länder ”missförstånd.

Kommentarer

  • Vi vet vår tur, om några år ' Det tar slut på utrymme i UTF-16. Meh.
  • Den grundläggande frågan är att texten är vilseledande hård. Ingen metod att representera den informationen på ett digitalt sätt kan vara okomplicerad. Det ' är av samma anledning att datum är svåra, kalendrar är svåra, tid är svåra, personliga namn är svåra, postadresser är svåra: när digitala maskiner skär varandra med mänskliga kulturella konstruktioner, komplexitet utbrott. Det är ett faktum i livet. Människor fungerar inte på digital logik.

Lämna ett svar

Din e-postadress kommer inte publiceras. Obligatoriska fält är märkta *