Pourquoi la question "UTF-8 byte[] to string" reste-t-elle d'actualité ?
\n\nImaginez : vous avez reçu un tableau d'octets d'une requête réseau, lu un fichier binaire ou désérialisé des données d'une API. À l'intérieur — du texte ordinaire en russe, anglais ou des emojis. Mais C# ne voit que byte[]. Votre tâche est de transformer ces zéros et uns en une chaîne string compréhensible.
On pourrait croire que c'est simple ? Un appel de méthode et c'est fait. Mais sur Stack Overflow, la question "How to convert UTF-8 byte[] to string" cumule des milliers de vues et des dizaines de réponses. Pourquoi ? Parce que le diable se cache dans les détails : encodage, performance, sécurité et exceptions inattendues.
\n\nDans cet article, nous ne donnerons pas seulement un code prêt à l'emploi. Nous comparerons les approches, mesurerons la vitesse, discuterons des pièges et choisirons le meilleur outil pour chaque tâche. Si vous programmez en C# et travaillez avec le réseau, les fichiers ou la sérialisation — ce contenu est pour vous.
\n\nLe problème : byte[] n'est pas une chaîne
\n\nEn C#, la chaîne string est stockée en encodage UTF-16. Mais les octets que vous avez reçus sont très probablement encodés en UTF-8 (standard d'Internet, JSON, la plupart des protocoles textuels). Une conversion directe est impossible — le compilateur générera une erreur.
Il faut un décodeur qui transforme une séquence d'octets UTF-8 en caractères UTF-16. Et c'est là que les choses deviennent intéressantes : le développeur a au moins trois voies fondamentalement différentes.
\n\nMéthode 1 : La classique — Encoding.UTF8.GetString
\n\nLa méthode la plus évidente et recommandée par Microsoft est d'utiliser la classe statique System.Text.Encoding :
byte[] utf8Bytes = { 72, 101, 108, 108, 111, 32, 208, 191, 209, 128, 208, 176, 208, 178, 208, 176 }; // "Hello права"\nstring result = Encoding.UTF8.GetString(utf8Bytes);\nConsole.WriteLine(result); // Sortie : Hello права\n\nAvantages :
\n- \n
- Simplicité — une ligne de code. \n
- Prise en charge de tous les encodages, y compris UTF-8, UTF-16, ASCII, Latin-1. \n
- Gestion intégrée du BOM (Byte Order Mark) — si un marqueur UTF-8 est présent au début du tableau, il sera ignoré. \n
- Sécurité — aucun bloc
unsafe. \n
Inconvénients :
\n- \n
- Chaque appel crée une nouvelle chaîne et un tampon interne. \n
- Si les octets sont corrompus ou contiennent une séquence UTF-8 invalide, la méthode lèvera par défaut une
DecoderFallbackException(si le fallback n'est pas configuré). \n - Pas optimal pour les très grands tableaux (centaines de mégaoctets) — double copie des données. \n
Quand l'utiliser ?
\nDans 95 % des cas. C'est la norme de l'industrie. Si vous n'écrivez pas un analyseur à haute charge ou ne travaillez pas avec des gigaoctets de journaux — utilisez Encoding.UTF8.GetString.
Méthode 2 : Rapide et dangereuse — unsafe avec des pointeurs
\n\nPour ceux qui recherchent la vitesse et n'ont pas peur de unsafe. L'idée : nous savons que UTF-8 et UTF-16 sont des encodages différents, mais si le tableau ne contient que des caractères ASCII (codes jusqu'à 127), chaque octet peut être "étiré" en un caractère de 2 octets sans décodage.
unsafe string UnsafeAsciiBytesToString(byte[] bytes)\n{\n fixed (byte* pBytes = bytes)\n {\n return new string((sbyte*)pBytes, 0, bytes.Length);\n }\n}\n\nCe code ne fonctionne que pour l'ASCII ! Pour le texte russe (caractères > 127), le résultat sera du charabia. Mais pour l'anglais pur, il est 2 à 3 fois plus rapide que Encoding.UTF8.GetString.
Avantages :
\n- \n
- Frais généraux minimaux — pas de copie, pas de décodage. \n
- Idéal pour l'analyse des en-têtes HTTP, des clés JSON (si elles sont en ASCII). \n
Inconvénients :
\n- \n
- Dangereux pour les caractères multi-octets — corruption des données. \n
- Nécessite l'autorisation
unsafedans le projet (pas toujours autorisé). \n - Ne gère pas