Pourquoi cette question est-elle si populaire sur Stack Overflow ?
Si vous avez déjà programmé en C# et avez été confronté à la nécessité de convertir une chaîne en tableau d'octets, vous vous êtes sûrement demandé : « Pourquoi dois-je spécifier l'encodage ? Une chaîne est juste une chaîne ! ». Cette question a recueilli des milliers de vues sur Stack Overflow non sans raison. Elle touche à une incompréhension fondamentale entre comment nous voyons le texte et comment l'ordinateur le voit.
Dans cet article, nous ne donnerons pas seulement un code prêt à l'emploi, mais nous comprendrons pourquoi Encoding.UTF8.GetBytes("hello") n'est pas une solution de contournement, mais la seule manière correcte. Vous apprendrez comment obtenir la représentation en octets des chaînes en C# sans risque de perte de données, et ce qui se cache derrière la magie de la « sélection automatique de l'encodage ».
Le mythe de la « chaîne sans encodage »
Beaucoup de débutants pensent qu'une chaîne en C# est simplement une séquence d'octets. Ce n'est pas le cas. En interne, string dans .NET est stockée en UTF-16 (caractères sur deux octets). Lorsque vous écrivez "Привет", cela occupe 12 octets en mémoire (6 caractères × 2 octets). Mais si vous essayez d'envoyer cette chaîne dans un fichier, sur le réseau ou dans une base de données, vous aurez presque toujours besoin d'un autre format — le plus souvent UTF-8.
Essayer d'obtenir des octets « sans encodage » revient à demander : « Comment traduire un livre du russe vers l'anglais sans préciser la langue ? ». C'est impossible. L'encodage est l'ensemble des règles de conversion des caractères en octets. Sans lui, vous obtiendrez un charabia.
Comment NE PAS faire (une erreur typique)
string text = "Hello, мир!";byte[] wrongBytes = System.Text.Encoding.Default.GetBytes(text); // MAUVAIS !Ce code utilise l'encodage système par défaut (généralement Windows-1251 sur une version russe de Windows). Si vous exécutez ce code sur une autre machine ou sous Linux, vous obtiendrez des octets différents. Votre application deviendra imprévisible.
L'approche correcte : spécification explicite de l'encodage
La seule manière fiable d'obtenir une représentation en octets cohérente des chaînes est de spécifier explicitement l'encodage. L'option la plus populaire et recommandée est UTF-8 :
string text = "Hello, мир!";byte[] utf8Bytes = System.Text.Encoding.UTF8.GetBytes(text);// Résultat : [72, 101, 108, 108, 111, 44, 32, 208, 188, 208, 184, 209, 128, 33]Ce code donnera toujours le même résultat sur n'importe quelle plateforme. Pourquoi ? Parce que UTF-8 est une norme internationale qui fonctionne partout de la même manière.
Autres options d'encodage (quand sont-elles nécessaires)
- ASCII — uniquement le latin, supprime tous les caractères >127.
- Unicode (UTF-16LE) — format interne de C#, mais inefficace pour le stockage.
- Windows-1251 — legacy, uniquement pour la compatibilité avec les anciens systèmes.
Pour 99 % des tâches modernes, utilisez Encoding.UTF8.
Et si je veux « sans spécification » ? Existe-t-il une astuce ?
Techniquement, vous pouvez utiliser BitConverter.ToString() ou du code unsafe avec des pointeurs, mais cela vous donnera les octets bruts UTF-16 stockés en mémoire. C'est une mauvaise idée pour plusieurs raisons :
- Le résultat dépend de la plateforme (Little-Endian vs Big-Endian).
- Vous obtiendrez des octets nuls supplémentaires pour le latin (chaque caractère occupe 2 octets).
- Lors d'un changement de version de .NET, la représentation interne peut changer (peu probable, mais possible).
Exemple de code dangereux à ne pas reproduire :
unsafe{ string text = "Hello"; fixed (char* ptr = text) { byte* bytePtr = (byte*)ptr; // Travailler avec les octets bruts UTF-16 }}Cela fonctionne, mais viole le principe « ne touche pas aux internes si tu n'en comprends pas les conséquences ».