2009-05-29 6 views
6

Nous avons récemment rencontré un exemple de code d'un fournisseur pour le hachage d'une clé secrète pour un appel de service Web, leur exemple était dans VB.NET que nous avons converti en C#. Cela a provoqué le hachage à produire une entrée différente. Il s'avère que la façon dont ils généraient la clé pour le cryptage était en convertissant un tableau char en une chaîne et retour à un tableau d'octets. Cela m'a conduit à la découverte que VB.NET et le codeur par défaut de C# fonctionnent différemment avec certains caractères.Pourquoi Encoding.Default.GetBytes() renvoie des résultats différents dans VB.NET et C#?

C#:

Console.Write(Encoding.Default.GetBytes(new char[] { (char)149 })[0]); 

VB:

Dim b As Char() = {Chr(149)} 
Console.WriteLine(Encoding.Default.GetBytes(b)(0)) 

La sortie C# est 63, alors que VB est la valeur de l'octet correct de 149. si vous utilisez une autre valeur, comme 145, etc. , la sortie correspond.

En passant par le débogage, l'encodeur par défaut VB et C# est SBCSCodePageEncoding.

Est-ce que quelqu'un sait pourquoi c'est?

J'ai corrigé l'exemple de code en initialisant directement un tableau d'octets, ce qu'il aurait dû être en premier lieu, mais je veux toujours savoir pourquoi l'encodeur, qui ne devrait pas être spécifique au langage, semble être juste cela.

Répondre

11

Si vous utilisez ChrW (149), vous obtenez un résultat différent - 63, identique au C#.

Dim b As Char() = {ChrW(149)} 
Console.WriteLine(Encoding.Default.GetBytes(b)(0)) 

Lire the documentation pour voir le différence- qui vous expliquera la réponse

+2

Voici un lien vers la documentation: http://msdn.microsoft .com/fr-us/library/613dxh46 (VS.80) .aspx –

+0

Bravo Jon- J'étais juste en train d'ajouter un lien. – RichardOD

+0

Merci! Je pensais que cela avait quelque chose à voir avec le bit Chr(), mais je ne savais pas comment éviter d'utiliser Chr() dans VB.NET. – Annagram

0

Le default encoding dépend de la machine et dépend du thread car il utilise la page de codes actuelle. Vous devriez généralement utiliser quelque chose comme Encoding.UTF8 afin de ne pas avoir à vous soucier de ce qui se passe quand une machine utilise unicode et une autre utilise 1252-ANSI.

0

Différents systèmes d'exploitation peuvent utiliser codages différents par défaut. Par conséquent, les données transmises d'un système d'exploitation à un autre peuvent être incorrectement traduites en . Pour vous assurer que les octets codés sont décodés correctement , votre application doit utiliser un codage Unicode, qui est, UTF8Encoding, UnicodeEncoding ou UTF32Encoding, avec un préambule. Une autre option consiste à utiliser un protocole de niveau supérieur pour garantir que le même format est utilisé pour le codage et le décodage.

de http://msdn.microsoft.com/en-us/library/system.text.encoding.default.aspx

pouvez-vous vérifier ce que chaque langue produit lorsque vous encodez explicitement en utilisant UTF8?

4

La fonction VB Chr prend un argument dans la gamme de 0 à 255, et il convertit à un personnage en utilisant la page de code par défaut. Il lèvera une exception si vous passez un argument en dehors de cette plage. ChrW prendra une valeur de 16 bits et retournera le système correspondant.

La valeur Char sans utiliser d'encodage donnera donc le même résultat que le code C# que vous avez affiché.

L'équivalent approximatif de votre code VB en C# sans utiliser la classe des chaînes VB (qui est la classe qui contient Chr et ChrW) serait:

char[] chars = Encoding.Default.GetChars(new byte[] { 149 }); 
Console.Write(Encoding.Default.GetBytes(chars)[0]); 
0

Je crois que l'équivalent en VB est ChrW (149) .

Ainsi, ce code VB ...

Dim c As Char() = New Char() { Chr(149) } 
    'Dim c As Char() = New Char() { ChrW(149) } 
    Dim b As Byte() = System.Text.Encoding.Default.GetBytes(c) 
    Console.WriteLine("{0}", Convert.ToInt32(c(0))) 
    Console.WriteLine("{0}", CInt(b(0))) 

produit la même sortie que ce code C# ...

var c = new char[] { (char)149 }; 
    var b = System.Text.Encoding.Default.GetBytes(c); 
    Console.WriteLine("{0}", (int)c[0]); 
    Console.WriteLine("{0}", (int) b[0]); 
Questions connexes