Stringlengteberekenaar

Plak een string en de tool geeft de lengte op vier verschillende manieren: .length in JavaScript-stijl (UTF-16-code-eenheden), Unicode-codepunten, grafeemclusters (wat gebruikers als één teken ervaren) en UTF-8-bytes (wat de databasekolom werkelijk opslaat). Voor elke string met emoji, vlaggen of combinerende tekens lopen deze waarden uiteen – en juist dat verschil veroorzaakt veel bugs.

De vier betekenissen van stringlengte

  1. 1

    UTF-16-code-eenheden

    Wat `str.length` teruggeeft in JavaScript: 1 voor de meeste tekens en 2 voor elk codepunt boven U+FFFF (emoji, oude schriften).

  2. 2

    Codepunten

    Eén per Unicode-scalair: emoji zijn elk 1, terwijl ZWJ-reeksen er meerdere bevatten.

  3. 3

    Grafeemclusters

    Wat een gebruiker "één teken" noemt: `🇺🇸` bestaat uit twee codepunten maar is één grafeem; `n̈` bevat eveneens twee codepunten, maar is slechts één grafeem.

  4. 4

    UTF-8-bytes

    Wat uw database opslaat: ASCII = 1 byte per teken; gangbare Europese tekens = 2 bytes; CJK = 3 bytes; de meeste emoji = 4 bytes.

Voorbeelden

String JS .length Codepunten Grafemen UTF-8-bytes
hello 5 5 5 5
café 4 4 4 5
😀 2 1 1 4
🇺🇸 4 2 1 8
👨‍👩‍👧 (familie) 8 5 1 18
n̈ (n + trema) 2 2 1 3

Waarom de cijfers verschillen

JavaScript-strings zijn gebaseerd op UTF-16, dus een codepunt boven U+FFFF wordt opgeslagen als een surrogaatpaar – twee UTF-16-code-eenheden. Daarom geldt "😀".length === 2. Gebruikers hebben hier een hekel aan, omdat ze 😀 als één teken beschouwen.

Grafemen gaan nog verder: een landvlag bestaat uit twee codepunten met een regio-indicator, die de gebruiker als één vlag ziet. In JavaScript is "🇺🇸".length === 4 – wat absurd lijkt, maar zo is het. Om over grafemen te itereren, gebruikt u Intl.Segmenter (modern), de bibliotheek grapheme-splitter, of handelt u het handmatig af.

UTF-8-bytes: wat uw database opslaat

Voor een kolom van het type VARCHAR(255):

  • In MySQL utf8 (feitelijk: utf8mb3) zijn de 255 bytes. café neemt 5 bytes in beslag, dus er passen 51 kopieën in.
  • In MySQL utf8mb4 (echte UTF-8, inclusief emoji) zijn het nog steeds bytes, maar de codering ondersteunt sequenties van 4 bytes.
  • In Postgres VARCHAR(255) zijn de 255 tekens (codepunten), geen bytes.
  • In SQL Server VARCHAR verschilt dit per collatie; NVARCHAR telt UCS-2-eenheden van 2 bytes.

Als u databasevelden dimensioneert op basis van het voor de gebruiker zichtbare aantal tekens, gebruik dan voor de zekerheid in UTF-8-kolommen het aantal bytes × 4 – elk grafeem kan tot 4 bytes per codepunt in beslag nemen, en ZWJ-reeksen voegen daar nog aan toe.

Tekens tellen in Twitter-stijl

Twitter telt een tweet volgens een eigen regel: codepunten, maar emoji en CJK-ideogrammen tellen voor 2. Een tweet die voor 100% uit ASCII bestaat kan 280 tekens hebben; een tweet met 140 emoji bereikt het maximum van 140 “tekens”.

SMS-tellen: 160 tekens in GSM 7-bit. Elk niet-GSM-teken (á, é, ñ, emoji) schakelt de codering om naar UCS-2, waardoor de berichtlengte daalt tot 70 tekens.

Praktische toepassingen

  • Databasekolommen dimensioneren – controleer het aantal bytes voordat u een migratie schrijft.
  • API-quota afdwingen – de meeste API’s tellen bytes, geen tekens.
  • Formuliervalidatie – toon de gebruiker een nauwkeurig aantal tekens dat overeenkomt met zijn verwachting (grafemen).
  • Prestaties debuggen – waarom itereert deze regex zo traag? Omdat de invoer in code-eenheden 3 keer langer is dan in grafemen.

Veelgestelde vragen

Dat emoji is een ZWJ-reeks die meerdere codepunten combineert (een familie-emoji bestaat bijvoorbeeld uit 7 codepunten). Twitter telt het volgens de Unicode-gewichtsregel als 2 tekens, terwijl uw editor er 1 grafeem van toont. Beide zijn technisch correct; ze meten alleen verschillende dingen.

Reken in UTF-8-databases voor de zekerheid 4 bytes per verwacht teken. Een veld van 100 tekens (grafemen) moet VARCHAR(400) bytes zijn, of, als uw database in tekens telt zoals Postgres, VARCHAR(100) met de juiste tekensetafhandeling.

In JavaScript hangt dit af van de normalisatievorm: een NFC-samengesteld teken (U+00E1) heeft lengte 1; een NFD-ontleed teken (U+0061 + U+0301) heeft lengte 2. Hetzelfde zichtbare teken, maar verschillende bytereeksen.

Emoji voor familie en beroep bestaan uit lange ZWJ-reeksen. Lettertypen zonder volledige ondersteuning renderen elk codepunt als een afzonderlijke glyph, waardoor 👨‍💻 uiteenvalt in 👨 + 💻. Het bijwerken van het lettertype van het besturingssysteem lost dit op.

Gerelateerde tools

Tool beschikbaar in andere talen