UTF-16

UTF-16 es una de varias formas de representar caracteres en memoria.

😎 → 0xD83D 0xDE0E → dos `code units` de 16 bits

Dart usa UTF-16

Si recorres una cadena con for (var i = 0; i < str.length; i++), estarás recorriendo code units, no caracteres visibles ni Unicode completos.

Unicode

Unicode es un estándar que asigna un número único (code point) a cada carácter.

😎 → U+1F60E
  • Cada code point puede ocupar 1 o 2 code units en memoria.

Si trabajas con emojis, idiomas no latinos o procesamiento de cadenas complejo, quizas necesites usar el tipo de dato Runes o el paquete characters para manipular texto Unicode.

Runes

Es el valor Unicode real de un carácter.

void main() {
   String texto = '😎';
   print(texto.runes.toList()); // [128526]
}

characters

Pero.... Algunos caracteres visibles están compuestos de múltiples Runes (como emojis o letras con tildes). Por eso characters se enfoca en grapheme clusters: lo que un usuario percibe como un carácter.

import 'package:characters/characters.dart';

void main() {
   String texto = '👨‍🚀'; // Hombre astronauta
   print(texto.runes.toList()); // [128104, 8205, 128640] // 👨 + ZWJ + 🚀
   print(texto.length); // 5 → número de code units (UTF-16)
   print(texto.runes.length); // 3 → número de Unicode code points (Runes)
   print(texto.characters.length); // 1 → número de caracteres visibles (graphemes)
}

¿Por qué texto.length da 5?

Por qué .length mide code units y el emoji ‘👨‍🚀’ está compuesto por tres Runes (👨 + ZWJ + 🚀):

Componente Unicode Code units en UTF-16
👨 U+1F468 2 code units
ZWJ U+200D 1 code unit
🚀 U+1F680 2 code units