Moet UTF-16 als schadelijk worden beschouwd?

Reacties

  • Niet echt correct. Ik leg uit, als je " שָׁ " schrijft, het samengestelde teken dat bestaat uit " ש ", " ָ " en " ׁ ", vovels, vervolgens verwijderen van elk ervan is logisch, je verwijdert één codepunt wanneer je op " backspace drukt " en verwijder alle tekens, inclusief vovels, wanneer u op " del " drukt. Maar u produceert nooit een illegale staat van de tekst – illegale codepunten. De situatie wanneer u op backspace drukt en illegale tekst krijgt, is dus onjuist.
  • CiscoIPPhone: als een bug " verschillende keren wordt gerapporteerd, door veel verschillende mensen ", en een paar jaar later schrijft een ontwikkelaar op een dev-blog dat " Geloof het of niet, het gedrag is meestal opzettelijk! ", dan (op zijn zachtst gezegd) ben ik geneigd te denken dat het ' waarschijnlijk niet de beste ontwerpbeslissing is die ooit is genomen. 🙂 Gewoon omdat het ' opzettelijk niet ' betekent dat het ' niet een bug.
  • Geweldig bericht. UTF-16 is inderdaad de " slechtste van twee werelden ": UTF8 heeft een variabele lengte, omvat heel Unicode, vereist een transformatie-algoritme van en naar onbewerkte codepunten, beperkt tot ASCII, en het heeft geen endianness-problemen. UTF32 heeft een vaste lengte, vereist geen transformatie, maar neemt meer ruimte in beslag en heeft endianness-problemen. Tot dusverre is het goed, je kunt UTF32 intern gebruiken en UTF8 voor serialisatie. Maar UTF16 heeft geen voordelen: het ' is afhankelijk van endianen, het is ' s variabele lengte, het neemt veel ruimte in beslag, het is ' s niet ASCII-compatibel. De moeite die nodig is om op de juiste manier met UTF16 om te gaan, zou beter besteed kunnen worden aan UTF8.
  • @Ian: UTF-8 NIET heeft dezelfde voorbehouden als UTF-8. U kunt geen surrogaten hebben in UTF-8. UTF-8 doet zich niet voor als iets dat het niet is, maar de meeste programmeurs die UTF-16 gebruiken, gebruiken het verkeerd. Ik weet. Ik ' heb ze keer op keer en opnieuw en opnieuw bekeken.
  • UTF-8 doet ook geen ' t hebben het probleem omdat iedereen het behandelt als een codering met variabele breedte. De reden dat UTF-16 het probleem heeft, is omdat iedereen het behandelt als een codering met een vaste breedte.

Antwoord

Dit is een oud antwoord.
Zie UTF-8 Everywhere voor de laatste updates.

Opinie: Ja, UTF-16 moet als schadelijk worden beschouwd . De reden dat het bestaat, is omdat er enige tijd geleden een misplaatst geloof was dat widechar zal zijn wat UCS-4 nu is.

Ondanks het “anglo-centrisme” van UTF-8, moet worden beschouwd als de enige bruikbare codering voor tekst. Men zou kunnen stellen dat broncodes van programmas, webpaginas en XML-bestanden, OS-bestandsnamen en andere computer-naar-computer tekstinterfaces nooit hadden mogen bestaan. Maar als ze dat doen, is tekst niet alleen voor menselijke lezers.

Aan de andere kant is UTF-8-overhead een kleine prijs, terwijl het aanzienlijke voordelen heeft. Voordelen zoals compatibiliteit met onbewuste code die alleen strings doorgeeft met char*. Dit is geweldig. Er zijn maar weinig nuttige karakters die in UTF-16 KORTER zijn dan in UTF-8.

Ik denk dat alle andere coderingen uiteindelijk zullen sterven. Dit houdt in dat MS-Windows, Java, ICU, python gebruik het niet meer als hun favoriet. Na lang onderzoek en discussies verbieden de ontwikkelingsconventies op mijn bedrijf het gebruik van UTF-16 overal behalve OS API-aanroepen, en dit ondanks het belang van de prestaties in onze applicaties en het feit dat we Windows gebruiken. Conversiefuncties zijn ontwikkeld om always-aangenomen-UTF8 std::string s te converteren naar native UTF-16, die Windows zelf ondersteunt niet correct .

Tegen mensen die zeggen “ gebruik wat nodig is waar het nodig is “, zeg ik: het heeft een enorm voordeel om overal dezelfde codering te gebruiken, en ik zie geen voldoende reden om anders doen. In het bijzonder denk ik dat het toevoegen van wchar_t aan C ++ een vergissing was, en dat geldt ook voor de Unicode-toevoegingen aan C ++ 0x. Wat moet worden geëist van STL-implementaties is dat elke std::string of char* parameter zou worden beschouwd als unicode-compatibel.

Ik ben ook tegen het “ gebruik wat je wilt “-benadering. Ik zie geen reden voor een dergelijke vrijheid. Er is genoeg verwarring over het onderwerp tekst, wat resulteert in al deze kapotte software. Dit gezegd hebbende, ben ik ervan overtuigd dat programmeurs eindelijk consensus moeten bereiken over UTF-8 als een goede manier. (Ik kom uit een niet-ascii-sprekend land en ben opgegroeid met Windows, dus er zou voor het laatst van mij worden verwacht dat ik UTF-16 zou aanvallen op basis van religieuze gronden).

Ik wil graag meer informatie delen over hoe ik tekst doe op Windows, en wat ik iedereen aanbeveel voor compilatietijd gecontroleerde unicode-correctheid, gebruiksgemak en betere multi-platformness van de code. De suggestie verschilt wezenlijk van wat gewoonlijk wordt aanbevolen als de juiste manier om Unicode op Windows te gebruiken. Maar diepgaand onderzoek van deze aanbevelingen leidde tot dezelfde conclusie. Dus hier geldt:

  • Gebruik wchar_t of std::wstring niet op een andere plaats dan aangrenzend aan APIs die UTF-16 accepteren.
  • Gebruik geen _T("") of L"" UTF-16 literals (deze moeten IMO uit de standaard worden gehaald , als onderdeel van UTF-16-deprecatie).
  • Gebruik geen typen, functies of hun afgeleiden die gevoelig zijn voor de _UNICODE constante, zoals LPTSTR of CreateWindow().
  • Toch is _UNICODE altijd gedefinieerd om geef geen char* strings door aan WinAPI om stil gecompileerd te worden
  • std::strings en char* overal in het programma wordt als UTF-8 beschouwd (tenzij anders vermeld)
  • Al mijn strings zijn std::string, hoewel je char * of string letterlijk kunt doorgeven aan convert(const std::string &).
  • Gebruik alleen Win32-functies die widechars accepteren (LPWSTR). Nooit degenen die LPTSTR of LPSTR accepteren. Geef parameters op deze manier door:

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

    (Het beleid gebruikt onderstaande conversiefuncties.)

  • Met MFC-strings :

    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); 
  • Werken met bestanden, bestandsnamen en fstream op Windows:

    • Nooit doorgeven std::string of const char* bestandsnaamargumenten voor fstream familie. MSVC STL ondersteunt geen UTF-8-argumenten, maar heeft een niet-standaard extensie die als volgt moet worden gebruikt:
    • std::string argumenten converteren naar std::wstring met Utils::Convert:

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

      We moeten handmatig verwijder de conversie, wanneer de houding van MSVC ten opzichte van fstream verandert.

    • Deze code is niet multi-platform en moet mogelijk handmatig worden gewijzigd in de toekomst
    • Zie fstream unicode-onderzoek / discussiecase 4215 voor meer informatie.
    • Maak nooit tekstuitvoerbestanden met niet-UTF8-inhoud
    • Vermijd het gebruik van fopen() voor RAII / OOD-redenen. Gebruik indien nodig _wfopen() en WinAPI-conventies hierboven.

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

Reacties

  • Ik kan ' niet akkoord gaan. De voordelen van utf16 ten opzichte van utf8 voor veel Aziatische talen domineren volledig de punten die u maakt. Het is naïef om te hopen dat Japanners, Thai, Chinezen, enz. Deze codering zullen opgeven. De problematische botsingen tussen tekensets zijn wanneer de tekensets meestal op elkaar lijken, behalve met verschillen. Ik stel voor te standaardiseren op: fixed 7bit: iso-irv-170; 8bit variabele: utf8; 16bit variabele: utf16; 32bit opgelost: ucs4.
  • @Charles: bedankt voor je input. Het is waar dat sommige BMP-tekens langer zijn in UTF-8 dan in UTF-16. Maar laten we ' s eerlijk zijn: het probleem zit niet in bytes die Chinese BMP-tekens opnemen, maar in de complexiteit van het softwareontwerp die ontstaat. Als een Chinese programmeur toch moet ontwerpen voor tekens met een variabele lengte, lijkt het erop dat UTF-8 nog steeds een kleine prijs is in vergelijking met andere variabelen in het systeem. Hij zou UTF-16 kunnen gebruiken als een compressie-algoritme als ruimte zo belangrijk is, maar zelfs dan zal het geen match zijn voor LZ, en na LZ of een andere generieke compressie nemen beide ongeveer dezelfde grootte en entropie aan.
  • Wat ik eigenlijk zeg, is dat vereenvoudiging die wordt geboden door het hebben van One-codering die ook compatibel is met bestaande char * -programmas, en die tegenwoordig het meest populair is voor alles, ondenkbaar is.Het is bijna zoals in goede oude " plaintext " dagen. Wilt u een bestand met een naam openen? U hoeft zich geen zorgen te maken wat voor soort unicode u doet, enz. Ik stel voor dat wij, ontwikkelaars, UTF-16 beperken tot zeer speciale gevallen van ernstige optimalisatie waarbij een klein beetje prestatie de moeite waard is om manmaanden werk te leveren.
  • Linux had een specifieke vereiste bij het kiezen om UTF-8 intern te gebruiken: compatibiliteit met Unix. Windows had dat niet ' nodig, en dus toen de ontwikkelaars Unicode implementeerden, voegden ze UCS-2-versies toe van bijna alle functies die tekst verwerken en lieten de multibyte-versies eenvoudig converteren naar UCS-2 en bel de anderen. Ze vervangt later UCS-2 door UTF-16. Linux daarentegen hield zich aan 8-bit coderingen en gebruikte dus UTF-8, omdat het in dat geval ' de juiste keuze is.
  • @Pavel Radzivilovsky : Tussen haakjes, uw geschriften over " Ik denk dat alle andere coderingen uiteindelijk zullen sterven. Dit houdt in dat MS-Windows, Java, ICU, Python het niet meer als hun favoriet gebruiken. " en " In het bijzonder denk ik dat het toevoegen van wchar_t aan C ++ een vergissing was, en dat geldt ook voor de Unicode-toevoegingen aan C ++ Ox. " zijn ofwel vrij naïef of heel erg arrogant . En dit komt van iemand die thuis codeert met een Linux en die blij is met de UTF-8-tekens. Om het bot te zeggen: Het won ' niet .

Antwoord

Unicode-codepunten zijn geen tekens! Soms zijn het niet eens glyphs (visuele vormen) .

Enkele voorbeelden:

  • Codepunten met Romeinse cijfers zoals “ⅲ”. (Een enkel teken dat eruitziet als “iii”.)
  • Tekens met accenten zoals “á”, die kunnen worden weergegeven als een enkel gecombineerd teken “\ u00e1” of een teken en gescheiden diakritische tekens “\ u0061 \ u0301 “.
  • Tekens zoals Griekse sigma met kleine letters, die verschillende vormen hebben voor het midden (” σ “) en het einde (” ς “) van woordposities, maar die als synoniemen voor zoeken moeten worden beschouwd.
  • Unicode discretionair koppelteken U + 00AD, dat al dan niet visueel wordt weergegeven, afhankelijk van de context, en dat wordt genegeerd voor semantisch zoeken.

De enige manieren om Unicode-bewerking te krijgen het recht is om een bibliotheek te gebruiken die is geschreven door een expert , of om een expert te worden en er zelf een te schrijven. Als je alleen codepunten telt, leef je in een staat van zonde.

Reacties

  • Dit. Heel erg dit. UTF-16 kan problemen veroorzaken, maar zelfs als u UTF-32 overal gebruikt, kan (en zal) u nog steeds problemen opleveren.
  • Wat is een karakter? Je kunt een codepunt als een personage definiëren en het vrijwel prima redden. Als je een voor de gebruiker zichtbare glyph bedoelt, is dat iets anders.
  • @tchrist zeker voor het toewijzen van ruimte is die definitie prima, maar voor iets anders? Niet zo veel. Als u een combinatieteken als enig teken behandelt (bijv. Voor een delete of ", neem dan de eerste N tekens " -bewerking), dan ' Zal vreemd en verkeerd gedrag vertonen. Als een codepunt alleen betekenis heeft in combinatie met ten minste een ander, kun je ' het niet op een verstandige manier alleen afhandelen.
  • @Pacerier, dit is laat op het feest, maar daar moet ik iets over zeggen. Sommige talen hebben zeer grote sets van mogelijke combinaties van diakritische tekens (cf. Vietnamees, d.w.z. mệt đừ). Het is erg handig om combinaties te hebben in plaats van één teken per diakritisch teken.
  • een kleine opmerking over terminologie: codepunten doen komen overeen met unicode-tekens ; waar Daniel het hier over heeft zijn door de gebruiker waargenomen karakters , die corresponderen met unicode grafeemclusters

Antwoord

Er is een eenvoudige vuistregel voor wat Unicode Transformation Form (UTF) moet gebruiken: – utf-8 voor opslag en communicatie – utf-16 voor gegevensverwerking – je zou kunnen gaan met utf-32 als het grootste deel van de platform-API die u gebruikt utf-32 is (gebruikelijk in de UNIX-wereld).

De meeste systemen gebruiken tegenwoordig utf-16 (Windows, Mac OS, Java, .NET, ICU , Qt). Zie ook dit document: http://unicode.org/notes/tn12/

Terug naar “UTF-16 als schadelijk”, Ik zou zeggen: zeker niet.

Mensen die bang zijn voor surrogaten (denken dat ze Unicode transformeren in een codering met variabele lengte) begrijpen de andere (veel grotere) complexiteiten niet die het in kaart brengen tussen karakters en een Unicode-codepunt zeer complex: het combineren van karakters, ligaturen, variatie selectors, besturingstekens, etc.

Lees deze serie hier gewoon http://www.siao2.com/2009/06/29/9800913.aspx en zie hoe UTF-16 een gemakkelijk probleem wordt.

Opmerkingen

  • Voeg enkele voorbeelden toe waar UTF-32 gebruikelijk is in de UNIX-wereld!
  • Nee, dat doe je niet UTF-16 wilt gebruiken voor gegevensverwerking. Het ' is vervelend. Het heeft alle nadelen van UTF-8, maar geen van de voordelen. Zowel UTF-8 als UTF-32 zijn duidelijk superieur aan de kwaadaardige hack die voorheen bekend stond als Mrs UTF-16, wiens meisjesnaam UCS-2 was.
  • Ik heb gisteren net een bug gevonden in de Java core String-klasse equalsIgnoreCase methode (ook andere in de stringklasse) die er nooit zou zijn geweest als Java UTF-8 of UTF-32 had gebruikt. Er zijn miljoenen van deze slapende bombshells in elke code die UTF-16 gebruikt, en ik ben ze beu. UTF-16 is een gemene pokken die onze software voor altijd en altijd met verraderlijke bugs plaagt. Het is duidelijk schadelijk, en zou moeten worden afgeschaft en verboden.
  • @tchrist Wow dus een niet-surrogaatbewuste functie (omdat het is geschreven toen er geen waren en helaas zo gedocumenteerd is dat het waarschijnlijk onmogelijk aan te passen – het specificeert .toUpperCase (char)) zal resulteren in het verkeerde gedrag? U ' weet dat een UTF-32-functie met een verouderde codepuntmap ' dit niet beter zou kunnen verwerken? Ook de hele Java API verwerkt surrogaten niet bijzonder goed en de meer ingewikkelde punten over Unicode helemaal niet – en met de latere zou de gebruikte codering helemaal niet doen '.
  • -1: Een onvoorwaardelijke .Substring(1) in .NET is een triviaal voorbeeld van iets dat de ondersteuning voor alle niet-BMP Unicode verbreekt. Alles dat UTF-16 gebruikt, heeft dit probleem; het ' is te gemakkelijk om het te behandelen als een codering met een vaste breedte, en je ziet problemen te zelden. Dat maakt het een actief schadelijke codering als je Unicode wilt ondersteunen.

Antwoord

Ja, absoluut.

Waarom? Het heeft te maken met het oefenen van code .

Als je kijkt naar deze codepunt gebruiksstatistieken op een groot corpus door Tom Christiansen zult u “zien dat trans-8bit BMP-codepunten verschillende orden worden gebruikt als de grootte groter is dan niet-BMP-codepunten:

 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 

Neem de TDD-uitspraak: “Niet-geteste code is gebroken code”, en herformuleer het als “niet-uitgeoefende code is gebroken code”, en bedenk hoe vaak programmeurs te maken hebben met niet-BMP codepunten.

Bugs die verband houden met het niet omgaan met UTF-16 als codering met variabele breedte, zullen veel vaker onopgemerkt blijven dan de equivalente bugs in UTF-8 . Sommige programmeertalen zijn nog steeds garandeer niet dat je UTF-16 krijgt in plaats van UCS-2, en sommige zogenaamde high-level programmeertalen bieden toegang tot code-eenheden in plaats van codepunten (zelfs C zou je toegang moeten geven tot codepunten als je wchar_t, ongeacht wat een plat formulieren doen).

Opmerkingen

  • " Bugs gerelateerd aan het niet omgaan met UTF-16 als het is veel waarschijnlijker dat een codering met variabele breedte onopgemerkt blijft dan de equivalente bugs in UTF-8. " Dit is de kern van het probleem, en dus het juiste antwoord.
  • Precies. Als je UTF-8-afhandeling vervormd is, zal het ' onmiddellijk duidelijk zijn. Als je UTF-8-afhandeling vervormd is, merk je ' alleen op of je ongebruikelijke Han-tekens of wiskundige symbolen invoert.
  • Heel waar, maar aan de andere kant hand, waar zijn unit-tests voor als je op geluk zou moeten vertrouwen om bugs te vinden in minder frequente gevallen?
  • @musiphil: dus, wanneer was de laatste keer dat je een unit-test voor niet-BMP-tekens hebt gemaakt?
  • Om mijn eerdere bewering verder uit te werken: zelfs met UTF-8 kun je er niet zeker van zijn dat je alle gevallen hebt behandeld nadat je slechts enkele werkende voorbeelden hebt gezien. Hetzelfde met UTF-16: je moet testen of je code zowel met niet-surrogaten als met surrogaten werkt. (Iemand zou zelfs kunnen beweren dat UTF-8 minstens vier grote gevallen heeft, terwijl UTF-16 er maar twee heeft.)

Antwoord

Ik zou willen voorstellen dat denken dat UTF-16 als schadelijk kan worden beschouwd, zegt dat je een beter begrip van unicode moet krijgen.

Aangezien ik ben neergehaald voor het presenteren van mijn mening over een subjectieve vraag, wil ik dit toelichten. Wat stoort u precies aan UTF-16? Zou u er de voorkeur aan geven als alles in UTF-8 is gecodeerd? UTF-7? Of Hoe zit het met UCS-4? Natuurlijk zijn bepaalde applicaties niet ontworpen om elke code van één teken te verwerken – maar ze zijn nodig, vooral in het wereldwijde informatiedomein van vandaag, voor communicatie tussen internationale grenzen.

Maar echt, als u vindt dat UTF-16 als schadelijk moet worden beschouwd omdat het verwarrend is of onjuist kan worden geïmplementeerd (unicode kan dat zeker zijn), welke methode van tekencodering zou dan als niet-schadelijk worden beschouwd?

BEWERKEN: ter verduidelijking: waarom zou u onjuiste implementaties van een standaard beschouwen als een weerspiegeling van de kwaliteit van de standaard zelf? Zoals anderen later hebben opgemerkt, betekent louter omdat een toepassing een tool op ongepaste wijze gebruikt, niet dat de tool zelf defect is. Als dat het geval was, zouden we waarschijnlijk dingen kunnen zeggen als var-trefwoord als schadelijk beschouwd of threading als schadelijk beschouwd. Ik denk dat de vraag de kwaliteit en aard van de standaard verwart met de problemen die veel programmeurs hebben bij het implementeren en het correct gebruiken, wat volgens mij meer het gevolg is van hun gebrek aan begrip van hoe unicode werkt, dan van unicode zelf.

Opmerkingen

  • -1: Hoe zit het met het aanpakken van een aantal van Artyom ' s objecti ons, in plaats van hem alleen maar te betuttelen?
  • BTW: Toen ik dit artikel begon te schrijven, wilde ik bijna " schrijven. Moet het artikel van Joel op Softeare van Unicode worden overwogen schadelijk " omdat er veel fouten zijn. Bijvoorbeeld: utf-8-codering duurt maximaal 4 tekens en niet 6. Het maakt ook geen onderscheid tussen UCS-2 en UTF-16 die echt verschillend zijn – en eigenlijk de problemen veroorzaken waar ik het over heb.
  • Ook moet worden opgemerkt dat toen Joel dat artikel schreef, de UTF-8-standaard 6 bytes WAS, niet 4. RFC 3629 veranderde de standaard in 4 bytes enkele maanden NADAT hij het artikel schreef. Zoals bijna alles op internet, loont het om uit meer dan één bron te lezen en je bewust te zijn van de leeftijd van je bronnen. De link was niet ' t bedoeld als het " einde allemaal ", maar eerder een startpunt.
  • Ik zou foto: utf-8 of utf-32 willen noemen: codering met variabele lengte in bijna alle gevallen (inclusief BMP) of codering met vaste lengte altijd.
  • @iconiK: Doe niet zo gek. UTF-16 is absoluut niet de de facto standaard voor het verwerken van tekst. Laat me een programmeertaal zien die geschikter is voor tekstverwerking dan Perl, die altijd (nou ja, voor meer dan een decennium) gebruikten abstracte karakters met een onderliggende UTF-8 representatie intern. Daarom verwerkt elk Perl-programma automatisch alle Unicode zonder dat de gebruiker constant met idiote surrogaten moet rondhangen. De lengte van een string is het aantal codepunten, niet de code-eenheden. Al het andere is pure domheid om het achterwaartse in achterwaartse compatibiliteit te plaatsen.

Antwoord

Er is niets mis met Utf- 16 codering. Maar talen die de 16-bits eenheden als tekens behandelen, moeten waarschijnlijk als slecht ontworpen worden beschouwd. Het hebben van een type met de naam “char” dat niet altijd een teken vertegenwoordigt, is behoorlijk verwarrend. Aangezien de meeste ontwikkelaars zullen verwachten dat een char-type een codepunt of -teken vertegenwoordigt, zal veel code waarschijnlijk breken als deze wordt blootgesteld aan tekens voorbij BMP.

Merk echter op dat zelfs het gebruik van utf-32 niet betekent dat elke 32- bitcodepunt zal altijd een teken vertegenwoordigen. Door het combineren van karakters kan een werkelijk karakter uit meerdere codepunten bestaan. Unicode is nooit triviaal.

BTW. Er is waarschijnlijk dezelfde klasse van bugs met platforms en applicaties die verwachten dat karakters 8-bit zijn, die Utf-8 gevoed worden.

Reacties

  • In Java ' s geval, als je naar hun tijdlijn kijkt ( java.com/en/javahistory/timeline.jsp), zie je dat de ontwikkeling van String voornamelijk plaatsvond terwijl Unicode 16 bits was (het veranderde in 1996). Ze moesten de mogelijkheid gebruiken om niet-BMP-codepunten te verwerken, dus de verwarring.
  • @Kathy: Niet echt een excuus voor C #. Over het algemeen ben ik het ermee eens dat er een CodePoint -type moet zijn met een enkel codepunt (21 bits), een CodeUnit -type, dat een enkele code-eenheid (16 bits voor UTF-16) en een Character type zou idealiter een volledig grafeem moeten ondersteunen. Maar dat maakt het functioneel equivalent aan een String
  • Dit antwoord is bijna twee jaar oud, maar ik kan ' t help maar geef er commentaar op. " Een type hebben met de naam ' char ' wat niet altijd een teken vertegenwoordigt, is mooi verwarrend. " En toch gebruiken mensen het de hele tijd in C en dergelijke om gehele getallen weer te geven die in een enkele byte kunnen worden opgeslagen.
  • En ik ' heb een lot C-code gezien die de tekencodering niet ' correct verwerkt.
  • C # heeft een ander excuus: het is ontworpen voor Windows en Windows is gebouwd op UCS-2 (het is ' erg vervelend dat zelfs vandaag de dag Windows APIs niet kunnen ondersteuning UTF-8). Bovendien denk ik dat Microsoft Java-compatibiliteit wilde (.NET 1.0 had een Java-compatibiliteitsbibliotheek, maar ze stopten al snel met Java-ondersteuning – ik ' gok dat dit komt door Sun ' s rechtszaak tegen MS?)

Antwoord

Mijn persoonlijke keuze is om altijd UTF-8 te gebruiken. Het is voor bijna alles de standaard op Linux. Het is achterwaarts compatibel met veel oudere apps. Er is een zeer minimale overhead in termen van extra ruimte die wordt gebruikt voor niet-Latijnse karakters ten opzichte van de andere UTF-formaten, en er is een aanzienlijke besparing in ruimte voor Latijnse karakters. Op het internet heersen Latijnse talen, en ik denk dat ze dat in de nabije toekomst zullen doen. En om een van de belangrijkste argumenten in het oorspronkelijke bericht aan te pakken: bijna elke programmeur is zich ervan bewust dat UTF-8 soms tekens van meerdere bytes bevat. Niet iedereen gaat hier correct mee om, maar ze zijn zich er meestal van bewust, wat meer is dan van UTF-16 kan worden gezegd. Maar u moet natuurlijk degene kiezen die het meest geschikt is voor uw toepassing. Daarom zijn er in de eerste plaats meer dan één.

Opmerkingen

  • UTF-16 is eenvoudiger voor alles binnen BMP, dat ' s waarom het zo veel wordt gebruikt. Maar ik ' ben ook een fan van UTF-8, het heeft ook geen problemen met de bytevolgorde, wat in zijn voordeel werkt.
  • Theoretisch wel, ja. In de praktijk zijn er zaken als bijvoorbeeld UTF-16BE, wat UTF-16 betekent in big endian zonder BOM. Dit is niet iets dat ik heb verzonnen, dit is een daadwerkelijke codering die is toegestaan in ID3v2.4-tags (ID3v2-tags zijn waardeloos, maar worden helaas veel gebruikt). En in dergelijke gevallen moet u endianness extern definiëren, omdat de tekst zelf geen BOM ' bevat. UTF-8 wordt altijd in één richting geschreven en het heeft geen ' zon probleem.
  • Nee, UTF-16 is niet eenvoudiger. Het is moeilijker. Het misleidt en misleidt u door te denken dat het een vaste breedte is. Al deze code is kapot en nog meer omdat je het pas merkt als het te laat is. GEVAL: Ik heb gisteren weer een stomme UTF-16-bug gevonden in de Java-kernbibliotheken, deze keer in String.equalsIgnoreCase, die werd achtergelaten in UCS-2 braindeath-buggy, en dus mislukt op 16/17 geldige Unicode-codepunten. Hoe lang bestaat die code al? Geen excuus om een buggy te zijn. UTF-16 leidt tot pure domheid en een wachtend ongeluk. Ren schreeuwend van UTF-16.
  • @tchrist Men moet een zeer onwetende ontwikkelaar zijn om niet te weten dat UTF-16 geen vaste lengte heeft. Als je begint met Wikipedia, lees je helemaal bovenaan het volgende: " Het levert een resultaat met variabele lengte op van één of twee 16-bits code-eenheden per codepunt ". Unicode FAQ zegt hetzelfde: unicode.org/faq//utf_bom.html#utf16-1 . Ik weet niet ' hoe UTF-16 iemand kan misleiden als het overal met variabele lengte wordt geschreven. Wat betreft de methode, deze is nooit ontworpen voor UTF-16 en mag ' niet als Unicode worden beschouwd, zo simpel is het.
  • @tchrist Heb je een bron voor uw statistieken? Hoewel goede programmeurs schaars zijn, denk ik dat dit goed is, omdat we waardevoller worden. 🙂 Wat betreft de Java APIs, op tekens gebaseerde onderdelen kunnen uiteindelijk verouderd raken, maar dit is geen garantie dat ze ' niet zullen worden gebruikt. En ze hebben zeker ' t verwijderd om compatibiliteitsredenen.

Antwoord

Nou, er is een codering die symbolen van een vaste grootte gebruikt. Ik bedoel zeker UTF-32. Maar 4 bytes voor elk symbool is te veel verspilde ruimte, waarom zouden we het in alledaagse situaties gebruiken?

Naar mijn mening komen de meeste problemen voort uit het feit dat sommige software viel achter de Unicode-standaard, maar waren niet snel om de situatie te corrigeren. Opera, Windows, Python, Qt – ze verschenen allemaal voordat UTF-16 algemeen bekend werd of zelfs tot stand kwam. Ik kan echter bevestigen dat er in Opera, Windows Verkenner en Kladblok geen problemen meer zijn met tekens buiten BMP (althans op mijn pc). Maar goed, als programmas geen surrogaatparen herkennen, gebruiken ze geen UTF-16. Welke problemen er ook ontstaan bij het omgaan met dergelijke programmas, ze hebben niets te maken met UTF-16 zelf.

Ik denk echter dat de problemen van legacy-software met alleen BMP-ondersteuning enigszins overdreven zijn. Tekens buiten BMP komen alleen in zeer specifieke gevallen en gebieden voor. Volgens de officiële Unicode-veelgestelde vragen , “zelfs in Oost-Aziatische tekst, zou de incidentie van surrogaatparen gemiddeld veel minder dan 1% van alle tekstopslag moeten zijn”.Natuurlijk mogen tekens buiten BMP niet “worden verwaarloosd omdat een programma anders niet Unicode-conform is, maar de meeste programmas zijn niet bedoeld om te werken met teksten die dergelijke tekens bevatten. Daarom als ze dat niet doen” t ondersteun het, het is onaangenaam, maar geen ramp.

Laten we nu eens kijken naar het alternatief. Als UTF-16 niet bestond, dan zouden we geen codering hebben die goed geschikt is voor niet-ASCII-tekst, en zou alle software die voor UCS-2 is gemaakt volledig opnieuw moeten worden ontworpen om Unicode-compatibel te blijven. Dit laatste zou hoogstwaarschijnlijk de acceptatie van Unicode alleen maar vertragen. We zouden ook niet in staat zijn geweest om de compatibiliteit met tekst in UCS-2 te behouden, zoals UTF-8 doet in relatie tot ASCII.

Nu, afgezien van alle legacy-problemen, wat zijn de argumenten tegen de codering Ik betwijfel echt of ontwikkelaars tegenwoordig niet weten dat UTF-16 een variabele lengte heeft, het is overal geschreven in de richting van Wikipedia. UTF-16 is veel minder moeilijk te ontleden dan UTF-8, als iemand op complexiteit wijst als een mogelijk probleem. Het is ook verkeerd om te denken dat het gemakkelijk is om te verknoeien met het bepalen van de stringlengte alleen in UTF-16. Als u UTF-8 of UTF-32 gebruikt, moet u zich er nog steeds van bewust zijn dat één Unicode-codepunt niet noodzakelijk één teken betekent. Afgezien daarvan denk ik niet dat er iets wezenlijks tegen de codering is.

Daarom denk ik niet dat de codering zelf als schadelijk moet worden beschouwd. UTF-16 is een compromis tussen eenvoud en compactheid, en het kan geen kwaad om te gebruiken wat nodig is waar het nodig is In sommige gevallen moet u compatibel blijven met ASCII en heeft u UTF-8 nodig, in sommige gevallen wilt u werken met Han-ideogrammen en ruimte besparen met UTF-16, in sommige gevallen heeft u universele representaties van tekens nodig met een vast teken. -length codering. Gebruik wat geschikter is, doe het gewoon goed.

Opmerkingen

  • Dat ' is een nogal oogkleed, Anglo-centrische visie, Malcolm. Bijna gelijk aan " ASCII is goed genoeg voor de VS – de rest van de wereld zou bij ons moeten passen ".
  • Eigenlijk ben ik ' m uit Rusland en kom ik de hele tijd cyrillisten tegen (inclusief mijn eigen programmas), dus ' Ik denk niet dat ik een Anglo-centrische kijk heb. 🙂 Het vermelden van ASCII is niet helemaal gepast, omdat het ' geen Unicode is en geen ' specifieke karakters ondersteunt. UTF-8, UTF-16, UTF-32 ondersteunen dezelfde internationale tekensets, ze zijn alleen bedoeld voor gebruik in hun specifieke gebieden. En dit is precies mijn punt: als je voornamelijk Engels gebruikt, gebruik dan UTF-8, als je voornamelijk cyrillische tekens gebruikt, gebruik UTF-16, als je oude talen gebruikt, gebruik dan UTF-32. Heel eenvoudig.
  • " Niet waar, Aziatische scripts zoals Japans, Chinees of Arabisch behoren ook tot BMP. BMP zelf is eigenlijk erg groot en zeker groot genoeg om alle scripts op te nemen die tegenwoordig worden gebruikt " Dit is allemaal zo verkeerd. BMP bevat 0xFFFF-tekens (65536). Chinezen alleen hebben meer dan dat. Chinese standaarden (GB 18030) hebben meer dan dat. Unicode 5.1 heeft al meer dan 100.000 tekens toegewezen.
  • @Marcolm: " BMP zelf is eigenlijk erg groot en zeker groot genoeg om alle scripts te bevatten die tegenwoordig worden gebruikt " Niet waar. Op dit punt heeft Unicode al ongeveer 100K tekens toegewezen, veel meer dan BMP kan verwerken. Er zijn grote hoeveelheden Chinese karakters buiten BMP. En sommige zijn vereist door GB-18030 (verplichte Chinese standaard). Andere zijn vereist door (niet-verplichte) Japanse en Koreaanse normen. Dus als je iets in die markten probeert te verkopen, heb je meer dan BMP-ondersteuning nodig.
  • Alles dat UTF-16 gebruikt maar alleen smalle BMP-tekens kan verwerken, gebruikt eigenlijk geen UTF-16. Het is buggy en kapot. Het uitgangspunt van het OP is correct: UTF-16 is schadelijk, omdat het na ï vijf mensen ertoe leidt om gebroken code te schrijven. U kunt Unicode-tekst aan of niet. Als je dat niet kunt, dan kies je een subset, die net zo stom is als tekstverwerking met alleen ASCII.

Answer

Jaren van Windows-internationaliseringswerk, vooral in Oost-Aziatische talen, hebben me misschien bedorven, maar ik neig naar UTF-16 voor interne-naar-het-programma-representaties van strings, en UTF-8 voor netwerk- of bestandsopslag van leesbare tekst. zoals documenten. UTF-16 kan gewoonlijk echter sneller worden verwerkt op Windows, dus dat is het belangrijkste voordeel van het gebruik van UTF-16 in Windows.

Door de sprong naar UTF-16 werd de geschiktheid van de gemiddelde productbehandeling drastisch verbeterd internationale tekst.Er zijn slechts een paar beperkte gevallen waarin de surrogaatparen in aanmerking moeten worden genomen (in feite deleties, invoegingen en regelafbreking) en het gemiddelde geval is meestal straight pass-through. En in tegenstelling tot eerdere coderingen zoals JIS-varianten, beperkt UTF-16 surrogaatparen tot een zeer smal bereik, dus de controle is erg snel en werkt voorwaarts en achterwaarts.

Toegegeven, het is ongeveer net zo snel correct in te voeren. gecodeerde UTF-8, maar er zijn ook veel kapotte UTF-8-toepassingen die surrogaatparen onjuist coderen als twee UTF-8-reeksen. Dus UTF-8 garandeert ook geen redding.

IE behandelt surrogaatparen redelijk goed sinds ongeveer 2000, ook al converteert het ze meestal van UTF-8-paginas naar een interne UTF-16-weergave; I “Ik ben er vrij zeker van dat Firefox het ook goed heeft, dus het kan me niet echt schelen wat Opera doet.

UTF-32 (ook bekend als UCS4) is zinloos voor de meeste applicaties omdat het zo veel ruimte in beslag neemt, dus het is zo ongeveer een niet-starter.

Reacties

  • Ik heb ' je commentaar op UTF-8 en surrogaatparen. Surrogaatparen is slechts een concept dat zinvol is in de UTF-16-codering, toch? Misschien kan code die rechtstreeks converteert van UTF-16-codering naar UTF-8-codering dit verkeerd krijgen, en daarin het probleem is het verkeerd lezen van de UTF-16, niet het schrijven van de UTF-8. Klopt dat?
  • Waar Jason ' s het over heeft, is software die implementeert opzettelijk UTF-8 op die manier: maak een surrogaatpaar en vervolgens UTF-8 en codeer elke helft afzonderlijk. De juiste naam voor die codering is CESU-8, maar Oracle (bijv.) Stelt het verkeerd voor als UTF-8. Java gebruikt een soortgelijk schema voor objectserialisatie, maar het ' is duidelijk gedocumenteerd als " Gewijzigde UTF-8 " en alleen voor intern gebruik. (Als we nu mensen zover konden krijgen om die documentatie te LEZEN en te stoppen met het gebruik van DataInputStream # readUTF () en DataOutputStream # writeUTF () ongepast …)
  • AFAIK, UTF-32 is nog steeds codering met variabele lengte, en niet gelijk aan UCS4, wat een specifiek bereik van codepunten is.
  • @Eonil, UTF-32 zal alleen te onderscheiden zijn van UCS4 als we een Unicode-standaard hebben die zoiets als een UCS5 of groter bevat.
  • @JasonTrue Toch zijn alleen de resultaten toevallig gelijk, niet gegarandeerd door het ontwerp. Hetzelfde gebeurde bij 32-bits geheugenadressering, Y2K, UTF16 / UCS2. Of hebben we enige garantie voor die gelijkheid? Als dat zo is, zou ik dat graag gebruiken. Maar ik ' wil geen mogelijk breekbare code schrijven. Ik schrijf een code op tekenniveau en het ontbreken van een gegarandeerde manier om te transcoderen tussen UTF < – > codepunt zit me erg dwars .

Answer

UTF-8 is zeker de juiste keuze, mogelijk vergezeld van UTF-32 voor interne gebruik in algoritmen die willekeurige toegang met hoge prestaties nodig hebben (maar waarbij het combineren van tekens wordt genegeerd).

Zowel UTF-16 als UTF-32 (evenals hun LE / BE-varianten) lijden aan endianess-problemen, dus zouden ze moeten nooit extern worden gebruikt.

Reacties

  • Constante tijd willekeurige toegang is ook mogelijk met UTF-8, gebruik gewoon code-eenheden in plaats van codepunten. Misschien heb je echt willekeurige toegang tot het codepunt nodig, maar ik ' heb nog nooit een use-case gezien, en je ' zou net zo goed willen willekeurige toegang tot een grafeemcluster.

Antwoord

UTF-16? absoluut schadelijk. Gewoon mijn korreltje zout hier, maar er zijn precies drie acceptabele coderingen voor tekst in een programma:

  • ASCII: bij het omgaan met dingen op laag niveau (bijv.: Microcontrollers) die zich niets beters kunnen veroorloven
  • UTF8: opslag in media met een vaste breedte, zoals bestanden
  • integer codepunten (“CP”?): een array van de grootste gehele getallen die handig zijn voor uw programmeertaal en platform (vervalt naar ASCII in de limiet van lage resorces). Moet int32 zijn op oudere computers en int64 op alles met 64-bits adressering.

  • Uiteraard interfaces met legacy-codegebruik welke codering nodig is om de oude code goed te laten werken.

Reacties

  • @simon buchan, de U+10ffff max zal uit het raam verdwijnen als (niet als) ze geen codepunten meer hebben. Dat gezegd hebbende, het gebruik van int32 op een p64-systeem voor snelheid is waarschijnlijk veilig, aangezien ik betwijfel of ze ' ll overschrijden U+ffffffff voordat u gedwongen om uw code voor 128-bits systemen rond 2050 te herschrijven. (Dat is het punt van " gebruik de grootste int die handig is " in tegenstelling tot " grootste beschikbare " (wat waarschijnlijk int256 of bignums of zoiets zou zijn).)
  • @David: Unicode 5.2 codeert 107.361 codepunten.Er zijn 867.169 ongebruikte codepunten. " wanneer " gewoon dom is. Een Unicode-codepunt is gedefinieerd als een getal van 0 tot 0x10FFFF, een eigenschap waarvan UTF-16 afhankelijk is. (Ook lijkt 2050 een veel te lage schatting voor 128-bits systemen wanneer een 64-bits systeem het volledige internet erin kan bevatten ' s adresruimte.)
  • @David: Uw " toen " verwees naar het opraken van Unicode-codepunten, niet een 128-bits switch die, ja, zal in de komende eeuwen zijn. In tegenstelling tot geheugen is er geen exponentiële groei van karakters, dus het Unicode Consortium heeft specifiek gegarandeerd dat het nooit een codepunt zal toewijzen boven U+10FFFF. Dit is echt een van die situaties waarin 21 bits is genoeg voor iedereen.
  • @Simon Buchan: Ten minste tot het eerste contact. 🙂
  • Unicode werd gebruikt om te garanderen dat er ook geen codepunten boven U + FFFF zouden zijn.

Antwoord

Unicode definieert codepunten tot 0x10FFFF (1.114.112 codes), alle applicaties die in een meertalige omgeving draaien met strings / bestandsnamen enz. zouden dat correct moeten afhandelen.

Utf-16 : omvat slechts 1.112.064 codes. Hoewel die aan het einde van Unicode afkomstig zijn van vliegtuigen 15-16 (Private Use Area). Het kan in de toekomst niet verder groeien, behalve het breken van Utf-16 concept.

Utf-8 : omvat theoretisch 2.216.757.376 codes. Het huidige bereik van Unicode codes kan worden weergegeven door een reeks van maximaal 4 bytes. Het heeft geen bytevolgorde probleem, het is “compatibel” met ascii.

Utf-32 : omvat theoretisch 2 ^ 32 = 4.294.967.296 codes. Momenteel is het niet gecodeerd met variabele lengte en zal dit waarschijnlijk niet in de toekomst zijn.

Deze feiten spreken voor zich. Ik begrijp niet dat ik pleit voor algemeen gebruik van Utf-16 . Het is gecodeerd met variabele lengte (kan niet worden benaderd door index), het heeft problemen om het hele Unicode bereik te dekken, zelfs op dit moment, de bytevolgorde moet worden afgehandeld, enz. Ik zie geen enkel voordeel, behalve dat het native wordt gebruikt in Windows en enkele andere plaatsen. Ook al is het bij het schrijven van multi-platform code waarschijnlijk beter om Utf-8 native te gebruiken en alleen aan de eindpunten conversies uit te voeren op platformafhankelijke manier (zoals al gesuggereerd). Als directe toegang via index noodzakelijk is en geheugen geen probleem is, moet Utf-32 worden gebruikt.

Het grootste probleem is dat veel programmeurs die te maken hebben met Windows Unicode = Utf-16 niet eens weten of negeren dat het is gecodeerd met variabele lengte.

De manier waarop het gewoonlijk is in * nix platform is redelijk goed, c strings (char *) geïnterpreteerd als Utf-8 gecodeerd, brede c strings (wchar_t *) geïnterpreteerd als Utf-32 .

Opmerkingen

  • Opmerking: UTF -16 dekt wel All Unicode omdat Unicode Consortium besloot dat 10FFFF het TOP-bereik van Unicode is en UTF-8 met een maximale lengte van 4 bytes heeft gedefinieerd en het bereik 0xD800-0xDFFF expliciet uitgesloten van een geldig codepuntbereik en dit bereik wordt gebruikt voor het maken van surrogaat paren. Dus elke geldige Unicode-tekst kan worden weergegeven met elk van deze coderingen. Ook over groeien naar de toekomst. Het lijkt niet ' t lijkt erop dat 1 miljoen codepunten in de verre toekomst niet genoeg zouden zijn.
  • @Kerrek: Onjuist: UCS-2 is geen geldige Unicode codering. Alle UTF- * -coderingen kunnen per definitie elk Unicode-codepunt vertegenwoordigen dat legaal is voor uitwisseling. UCS-2 kan veel minder vertegenwoordigen dan dat, plus een paar meer. Herhaal: UCS-2 is geen geldige Unicode-codering, meer dan ASCII is dat wel.
  • " Ik begrijp niet dat het pleiten voor algemeen gebruik van Utf- 8 . Het is gecodeerd met variabele lengte (kan niet worden benaderd door index) "
  • @Ian Boyd, de noodzaak om toegang te krijgen tot het individuele teken van een string in een willekeurig toegangspatroon is ongelooflijk overdreven. Het komt ongeveer net zo vaak voor als het willen berekenen van de diagonaal van een matrix van karakters, wat super zeldzaam is. Strings worden vrijwel altijd opeenvolgend verwerkt en aangezien UTF-8 char N + 1 toegang krijgen tot UTF-8 char N is O (1), is er geen probleem. Er is buitengewoon weinig behoefte om willekeurige toegang tot strings te maken. Of je denkt dat het de opslagruimte waard is om naar UTF-32 te gaan in plaats van UTF-8, is jouw eigen mening, maar voor mij is het helemaal geen probleem.
  • @tchrist, ik geef toe uw strings worden vrijwel altijd opeenvolgend verwerkt als u omgekeerde iteratie opneemt als " opeenvolgend " en dat een beetje verder vergelijkt met het einde van een string naar een bekende string. Twee veel voorkomende scenarios zijn het afkappen van spaties vanaf het einde van strings en het controleren van de bestandsextensie aan het einde van een pad.

Answer

Voeg dit toe aan de lijst:

Het gepresenteerde scenario is eenvoudig (nog eenvoudiger omdat ik het hier zal presenteren dan het oorspronkelijk was! ): 1. Een WinForms-tekstbox staat op een formulier, leeg. Het heeft een MaxLength ingesteld op 20 .

2.De gebruiker typt in de TextBox, of misschien plakt er tekst in.

3. Het maakt niet uit wat je typt of plakt in de TextBox, je bent beperkt tot 20, hoewel het sympathiek piept bij tekst na de 20 (YMMV hier; ik heb mijn geluidsschema gewijzigd om mij dat effect te geven!).

4. Het kleine pakket tekst wordt dan ergens anders naartoe gestuurd om een spannend avontuur te beginnen.

Dit is een eenvoudig scenario en iedereen kan dit in zijn vrije tijd opschrijven. Ik heb het net zelf opgeschreven in meerdere programmeertalen met WinForms, omdat ik me verveelde en het nog nooit eerder had geprobeerd. En met tekst in meerdere echte talen omdat ik zo bedraad ben en meer toetsenbordindelingen heb dan mogelijk wie dan ook in het hele gekke universum.

Ik heb zelfs het formulier Magic Carpet Ride genoemd, om de verveling te verzachten.

Dit werkte niet, voor wat het waard is.

Dus in plaats daarvan heb ik het volgende ingevoerd 20 tekens in mijn Magic Carpet Ride vorm:

0123401234012340123 𠀀

Oh oh.

Dat laatste teken is U + 20000, het eerste Uitbreiding B ideografie van Unicode (ook bekend als U + d840 U + dc00, voor zijn goede vrienden waarvan hij zich niet schaamt om als het ware ontkleed te worden) …

voer hier een afbeeldingbeschrijving in

En nu hebben we een balspel.

Omdat wanneer TextBox. MaxLength heeft het over

Haalt of stelt het maximale aantal tekens in dat handmatig in het tekstvak kan worden ingevoerd.

wat het werkelijk betekent is

Haalt of zet het maximale aantal UTF-16 LE-kabeljauw e eenheden die handmatig in het tekstvak kunnen worden ingevoerd en genadeloos de levende rotzooi zullen afkappen uit elke reeks die schattige spelletjes probeert te spelen met het linguïstische karakter, dat alleen iemand die zo geobsedeerd is als die Kaplan-kerel aanstootgevend zal zijn (geez hij moet lees meer!).

Ik zal proberen om het document bijgewerkt te krijgen …
Vaste lezers die onthoud dat mijn UCS-2 naar UTF-16 -serie zal opmerken dat ik ongelukkig ben met het simplistische idee van TextBox.MaxLength en hoe het op zijn minst dit geval moet aanpakken waarin zijn draconische gedrag een illegale reeks creëert, een die andere delen van het .Net Framework een

  • System.Text.EncoderFallbackException kunnen opleveren : Unicode-teken \ uD850 op index 0 kan niet worden vertaald naar de gespecificeerde codepagina. *

uitzondering als u deze string ergens anders in het .Net Framework doorgeeft (zoals mijn collega Dan Thompson deed).

Oké, misschien is de volledige UCS-2 tot UTF-16-serie buiten het bereik van velen.
Maar isn “Is het redelijk om te verwachten dat TextBox.Text geen System.String zal produceren die geen ander stuk van het .Net Framework zal veroorzaken? Ik bedoel, het is niet zo dat er een kans is in de vorm van een gebeurtenis op het besturingselement dat je vertelt over de aanstaande afkapping waar je gemakkelijk de slimmere validatie kunt toevoegen – validatie die het besturingselement zelf niet erg vindt. Ik zou ga zelfs zo ver om te zeggen dat deze punkcontrole een veiligheidscontract verbreekt dat zelfs tot veiligheidsproblemen kan leiden als je kunt classificeren waardoor onverwachte uitzonderingen een toepassing beëindigen als een grove vorm van denial of service.Waarom zou een WinForms-proces of -methode of algoritme of techniek ongeldige resultaten opleveren?

Bron: Michael S.Kaplan MSDN Blog

Reacties

  • Bedankt, zeer goede link! Ik ' heb het toegevoegd aan de lijst met problemen in de vraag.

Antwoord

Ik zou niet per se zeggen dat UTF-16 schadelijk is. Het is niet elegant, maar het dient zijn doel van achterwaartse compatibiliteit met UCS-2, net zoals GB18030 doet met GB2312, en UTF-8 doet met ASCII.

Maar een fundamentele wijziging aanbrengen in de structuur van Unicode in de midstream, nadat Microsoft en Sun enorme APIs rond 16-bits tekens hadden gebouwd, was schadelijk. Het niet bekend maken van de verandering was meer schadelijk.

Reacties

  • UTF-8 is een superset van ASCII , maar UTF-16 is GEEN superset van UCS-2. Hoewel het bijna een superset is, resulteert een correcte codering van UCS-2 in UTF-8 in de gruwel die bekend staat als CESU-8; UCS-2 heeft geen ' geen surrogaten, alleen gewone codepunten, dus ze moeten als zodanig worden vertaald. Het echte voordeel van UTF-16 is dat het ' s gemakkelijker is om een UCS-2 codebase te upgraden dan een volledige herschrijving voor UTF-8. Grappig, hè?
  • Natuurlijk, technisch gezien is UTF-16 niet ' een superset van UCS-2, maar wanneer waren U + D800 naar U + DFFF ooit gebruikt voor iets anders dan UTF-16 surrogaten?
  • Doet ' er niet toe. Elke verwerking anders dan blindelings door de bytestream gaan, vereist dat u de surrogaatparen decodeert, wat u ' niet kunt doen als u ' opnieuw behandelt het als UCS-2.

Antwoord

UTF-16 is de beste compromis tussen verwerking en ruimte en daarom gebruiken de meeste grote platforms (Win32, Java, .NET) het voor interne weergave van strings.

Opmerkingen

  • -1 omdat UTF-8 waarschijnlijk kleiner of niet significant verschillend is. Voor bepaalde Aziatische scripts is UTF-8 drie bytes per glyph, terwijl UTF-16 slechts twee is, maar dit is gebalanceerd doordat UTF-8 slechts één byte is voor ASCII (wat vaak zelfs in Aziatische talen voorkomt in productnamen, opdrachten en dergelijke). Verder geeft een glyph in de genoemde talen meer informatie dan een Latijns teken, dus het is gerechtvaardigd zodat het meer ruimte inneemt.
  • Ik zou het combineren van de wor niet willen noemen e kanten van beide opties een goed compromis.
  • Het is ' niet eenvoudiger dan UTF-8. Het ' heeft ook een variabele lengte.
  • Debatten over de voordelen van UTF-16 terzijde laten: wat u noemde is niet de reden voor Windows, Java of .NET met UTF-16. Windows en Java dateren uit een tijd waarin Unicode een 16-bits codering was. UCS-2 was toen een redelijke keuze. Toen Unicode een 21-bits codering werd, was het migreren naar UTF-16 de beste keuze die bestaande platforms hadden. Dat had niets te maken met gebruiksgemak of ruimtegebrek. Het ' is slechts een kwestie van legacy.
  • .NET neemt hier de Windows-erfenis over.

Antwoord

Ik “heb het punt van UTF-16 nooit begrepen. Als je de meest ruimtebesparende weergave wilt, gebruik dan UTF-8. Als je dat wilt kunnen behandel tekst als een vaste lengte, gebruik UTF-32. Als je geen van beide wilt, gebruik dan UTF-16. Erger nog, aangezien alle gewone (basis meertalige vlak) tekens in UTF-16 in één codepunt passen, zijn er bugs die veronderstellen dat UTF-16 een vaste lengte heeft, zal subtiel en moeilijk te vinden zijn, terwijl als je dit probeert met UTF-8, je code snel en luid zal mislukken zodra je probeert te internationaliseren.

Antwoord

Aangezien ik nog geen commentaar kan geven, plaats ik dit als antwoord, aangezien het lijkt alsof ik anders geen contact kan opnemen met de auteurs van utf8everywhere.org. Het is jammer dat ik niet automatisch het commentaarprivilege krijg, aangezien ik genoeg reputatie heb op andere stackexchanges.

Dit is bedoeld als commentaar op het advies: Ja, UTF-16 moet als schadelijk worden beschouwd antwoord.

Een kleine correctie:

Om te voorkomen dat iemand per ongeluk een UTF-8 char* doorgeeft aan ANSI-stringversies van Windows-API-functies, moet men definieer UNICODE, niet _UNICODE. _UNICODE wijst functies zoals _tcslen toe aan wcslen, niet MessageBox naar MessageBoxW. In plaats daarvan zorgt de UNICODE define voor het laatste. Als bewijs is dit afkomstig van MS Visual Studio 2005 “s WinUser.h header:

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

Op zijn minst deze fout moet worden gecorrigeerd op utf8everywhere.org.

Een suggestie:

Misschien moet de gids een voorbeeld bevatten van expliciet gebruik van de Wide- stringversie van een datastructuur, om het minder gemakkelijk te missen / vergeten.Het gebruik van Wide-string-versies van datastructuren naast het gebruik van Wide-string-versies van functies maakt het nog minder waarschijnlijk dat men per ongeluk een ANSI-string-versie van een dergelijke functie aanroept.

Voorbeeld van het voorbeeld:

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); } 

Reacties

  • Akkoord; bedankt! We zullen het document bijwerken. Het document heeft nog meer ontwikkeling nodig en informatie over databases. We ontvangen graag bijdragen met formuleringen.
  • @PavelRadzivilovsky _UNICODE is er nog steeds 🙁
  • bedankt voor het eraan herinneren. Cubus, Jelle, Wil je een gebruiker van onze SVN?
  • @Pavel Tuurlijk, zou het op prijs stellen!
  • @JelleGeerts: mijn excuses voor deze vertraging. Je kunt altijd contact met ons opnemen via onze e-mails (gelinkt van het manifest) of Facebook. We zijn gemakkelijk te vinden. Hoewel ik denk dat we het probleem dat u hier naar voren bracht hebben opgelost (en ik u daar heb gecrediteerd), zijn de hele UTF-8 versus UTF-16-debatten nog steeds relevant. Als u meer wilt draag gerust contact met ons op via die privékanalen.

Antwoord

Iemand zei dat UCS4 en UTF-32 hetzelfde. Nee, maar ik weet wat je bedoelt. Een van hen is echter een codering van de andere. Ik wou dat ze “dachten om endianness vanaf de eerste te specificeren, zodat we niet zouden hebben dat de endianess-strijd hier ook zou worden uitgevochten. Hadden ze dat niet kunnen zien aankomen? UTF-8 is tenminste overal hetzelfde re (tenzij iemand de originele specificatie volgt met 6 bytes).

Als je UTF-16 gebruikt, moet je de afhandeling van multibyte-tekens opnemen. Je kunt “niet naar het N-de karakter gaan door 2N te indexeren in een byte-array. Je moet het lopen, of je hebt karakterindices. Anders heb je een bug geschreven.

De huidige conceptspecificatie van C ++ zegt dat UTF-32 en UTF-16 little-endian, big-endian en niet-gespecificeerde varianten kunnen hebben. Werkelijk? Als Unicode had gespecificeerd dat iedereen vanaf het begin little-endian moest doen, dan zou het allemaal eenvoudiger zijn geweest. (Ik zou ook prima zijn geweest met big-endian.) In plaats daarvan hebben sommige mensen het op de een of andere manier geïmplementeerd, en nu zitten we voor niets vast met dwaasheden. Soms is het beschamend om een software-engineer te zijn. / p>

Opmerkingen

  • Niet-gespecificeerde endianess moet stuklijst bevatten als het eerste teken, gebruikt om te bepalen op welke manier de string moet worden gelezen. UCS-4 en UTF-32 zijn tegenwoordig inderdaad hetzelfde, d.w.z. een numerieke UCS-waarde tussen 0 en 0x10FFFF opgeslagen in een 32 bit geheel getal.
  • @Tronic: Technisch gezien is dit niet waar. Hoewel UCS-4 elk 32-bits geheel getal kan opslaan, is het UTF-32 verboden om codepunten zonder tekens op te slaan die niet mogen worden uitgewisseld, zoals 0xFFFF, 0xFFFE en alle surrogaten. UTF is een transportcodering, geen interne.
  • Endianness-problemen zijn onvermijdelijk zolang verschillende processors verschillende bytevolgordes blijven gebruiken. Het zou echter leuk zijn geweest als er een " voorkeur " bytevolgorde zou zijn voor bestandsopslag van UTF-16.
  • Hoewel UTF-32 een vaste breedte heeft voor codepunten , heeft het geen vaste breedte voor tekens . (Gehoord van iets genaamd " tekens combineren "?) Dus je kunt ' niet gaan naar de N ' het teken door simpelweg 4N in de byte-array te indexeren.

Antwoord

Ik denk niet dat het schadelijk is als de ontwikkelaar voorzichtig genoeg is.
En ze moeten deze afweging accepteren als ze het ook goed weten.

Als Japanse softwareontwikkelaar vind ik UCS-2 groot genoeg en het beperken van de ruimte vereenvoudigt kennelijk de logica en vermindert het runtime-geheugen, dus het gebruik van utf-16 onder UCS-2-beperking is goed genoeg.

Er zijn bestandssystemen of andere applicaties die ervan uitgaan dat codepunten en bytes proportioneel zijn, zodat gegarandeerd kan worden dat het ruwe codepuntnummer geschikt is voor een opslag met een vaste grootte.

Een voorbeeld is NTFS en VFAT die UCS-2 specificeren als hun bestandsnaamopslagcodering.

Als dat voorbeeld echt wil uitbreiden om UCS-4 te ondersteunen, kan ik ermee instemmen om utf-8 toch voor alles te gebruiken, maar vaste lengte heeft goede punten zoals:

  1. kan de grootte garanderen op basis van lengte (gegevensgrootte en codepuntlengte is proportioneel)
  2. kan het coderingsnummer gebruiken voor het opzoeken van hash
  3. niet-gecomprimeerde gegevens hebben een redelijke grootte (vergeleken met utf-32 / UCS-4)

In de toekomst, wanneer geheugen / verwerkingskracht goedkoop is, zelfs in ingebedde apparaten, kunnen we accepteren dat het apparaat een beetje traag is voor extra cachemissers of paginafouten en extra geheugen gebruik, maar dit zal in de nabije toekomst niet gebeuren denk ik …

Reacties

  • Voor degenen die deze opmerking lezen, is het vermeldenswaard dat UCS- 2 is niet hetzelfde als UTF-16. Zoek de verschillen op om ze te begrijpen.

Antwoord

“Moet een van de meest populaire coderingen, UTF-16, als schadelijk worden beschouwd? “

Heel goed mogelijk, maar de alternatieven hoeven niet per se als veel beter te worden beschouwd.

Het fundamentele probleem is dat er veel verschillende concepten zijn over: glyphs, karakters, codepunten en bytesequenties. De koppeling tussen elk van deze is niet triviaal, zelfs met behulp van een normalisatiebibliotheek. (Sommige tekens in Europese talen die zijn geschreven met een op het Latijn gebaseerd script, worden bijvoorbeeld niet geschreven met een enkel Unicode-codepunt. En dat is aan het eenvoudigere einde van de complexiteit!) Dit betekent dat alles correct is nogal verbazingwekkend moeilijk; bizarre bugs zijn te verwachten (en in plaats van er hier alleen maar over te klagen, vertel je de beheerders van de betreffende software).

De enige manier waarop UTF- 16 kan als schadelijk worden beschouwd in tegenstelling tot, bijvoorbeeld, UTF-8 is dat het een andere manier heeft om codepunten buiten de BMP te coderen (als een paar surrogaten). Als code toegang wil krijgen tot of itereren per codepunt, dat betekent dat het zich bewust moet zijn van het verschil. OTOH, het betekent wel dat een substantiële hoeveelheid bestaande code die “tekens” veronderstelt altijd in een hoeveelheid van twee bytes past – een vrij veel voorkomende veronderstelling, indien verkeerd blijf tenminste werken zonder alles opnieuw op te bouwen. Met andere woorden, je krijgt in ieder geval zie die karakters Dat wordt niet goed afgehandeld!

Ik zou je vraag op zijn kop zetten en zeggen dat de hele verdomde herrie van Unicode als schadelijk moet worden beschouwd en dat iedereen een 8-bits codering zou moeten gebruiken, behalve Ik heb (in de afgelopen 20 jaar) gezien waar dat toe leidt: vreselijke verwarring over de verschillende ISO 8859-coderingen, plus de hele reeks coderingen die worden gebruikt voor Cyrillisch en de EBCDIC-suite, en … nou, Unicode voor al zijn fouten verslaat dat . Was het maar niet “zon akelig compromis tussen verschillende landen” misverstanden.

Reacties

  • Als we geluk kennen, zullen we over een paar jaar ' Ik merk dat we te weinig ruimte hebben in UTF-16. Meh.
  • Het fundamentele probleem is dat tekst bedrieglijk moeilijk is. Geen enkele benadering om die informatie op een digitale manier weer te geven, kan ongecompliceerd zijn. Het ' is om dezelfde reden dat datums moeilijk zijn, kalenders moeilijk, tijd is moeilijk, persoonlijke namen moeilijk zijn, postadressen moeilijk: wanneer digitale machines elkaar kruisen met menselijke culturele constructies, complexiteit barst los. Het is een feit in het leven. Mensen functioneren niet op basis van digitale logica.

Geef een reactie

Het e-mailadres wordt niet gepubliceerd. Vereiste velden zijn gemarkeerd met *