2009-02-17 10 views
3

Dans notre API, nous utilisons byte [] pour envoyer des données sur le réseau. Tout a bien fonctionné, jusqu'au jour où nos clients "étrangers" ont décidé de passer/recevoir des caractères Unicode. Autant que je sache, les caractères Unicode occupent 2 octets, cependant, nous allouons seulement 1 octet dans le tableau d'octets pour eux.Conversion d'un caractère unicode de l'octet

Voici comment nous lisons le caractère de l'octet [] tableau:

 // buffer is a byte[6553] and index is a current location in the buffer 
     char c = System.BitConverter.ToChar(buffer, m_index); 
     index += SIZEOF_BYTE; 

     return c; 

Donc, la question actuelle est l'API reçoit un étrange caractère Unicode, quand je regarde le hexadécimal Unicode. J'ai trouvé que le dernier octet significatif est correct, mais l'octet le plus significatif a une valeur quand il est censé être 0. Une solution de contournement rapide, jusqu'à présent, a été de 0x00FF & c pour filtrer le msb.

Veuillez suggérer la bonne approche pour gérer les caractères Unicode provenant de la socket?

Merci.

Solution:

Bravo à Jon:

char c = (char) Tampon [m_index]; Et comme il l'a mentionné, la raison pour laquelle cela fonctionne, c'est parce que le client api reçoit un caractère occupant seulement un octet, et BitConverter.ToChar en utilise deux, d'où le problème de sa conversion. Je suis toujours surpris de voir pourquoi cela a fonctionné pour certains personnages et pas pour les autres, car cela aurait dû échouer dans tous les cas.

Merci les gars, bonnes réponses!

+1

"Autant que je sache, les caractères Unicode occupent 2 octets" c'est faux. la meilleure simplification est de penser que "ASCII est obsolète, les bytestreams de texte sont UTF8", et par conséquent toujours faire un encodage/décodage pour convertir interne à/de UTF8 chaque fois que vous les sortez/dans votre application. – Javier

+1

Cette simplification est fausse, car elle suppose UTF-8 partout - ce qui n'est * certainement * pas le cas. Oui, UTF-8 est très commun, mais supposer qu'il est omniprésent est une erreur. La meilleure attitude n'est pas de simplifier du tout: vous devez toujours connaître l'encodage lorsque vous codez/décodez. Ne présumez pas. –

+0

Dans ce cas, je ne suppose pas, comme j'ai regardé le code côté serveur, et vu qu'il est en effet envoyer un caractère emballé en 1 octet (sans aucun encodage). Néanmoins, je suis d'accord qu'un codage correct devrait être étudié avant l'encodage/décodage. Merci –

Répondre

5

Vous devez utiliser Encoding.GetString, en utilisant le codage le plus approprié.

Je ne comprends pas très bien votre situation, mais la classe Encoding est presque certain d'être la façon de le gérer.

Qui est en contrôle des données ici? Votre code, ou celui de vos clients? Avez-vous défini le format correct?

EDIT: Ok, j'ai jeté un autre coup d'oeil à votre code: BitConverter.ToChar renvoie "Un caractère formé par deux octets commençant à startIndex." Si vous voulez seulement utiliser un octet, juste jeter:

char c = (char) buffer[m_index]; 

Je suis surpris de votre code a travaillé du tout, car il enfreindrait tout moment l'octet suivant était non nul.

+0

Cela peut être un peu difficile, car nous recevons également des chaînes du réseau via str = System.Text.ASCIIEncoding.ASCII.GetString(). Peut-être que je ne comprends pas votre réponse. Pourriez-vous me montrer un exemple de cela? Merci –

+0

Si vous utilisez Encoding.ASCII, vous ne serez pas en mesure de gérer les caractères accentués. Je vous suggère de fournir plus d'informations dans la question. –

0

Vous devriez regarder la fonction System.Text.ASCIIEncoder.ASCII.GetString qui prend un tableau byte [] et le convertit en une chaîne (pour ascii).

Et System.Text.UTF8Encoder ou System.Text.UTF16Encoder pour les chaînes Unicode dans les codages UTF8 ou UTF16.

Il existe également des fonctions pour convertir des chaînes en octets [] dans les classes ASCIIEncoding, UTF8Encoding et UTF16Encoding: voir les fonctions GetBytes (String).

0

Les caractères Unicode peuvent prendre jusqu'à quatre octets, mais rarement les messages sont codés sur le fil en utilisant 4 octets pour chaque caractère. Plutôt, des schémas tels que UTF8 ou UTF16 sont utilisés qui n'apportent que des octets supplémentaires si nécessaire. Jetez un oeil à la classe Encoding.

0

Les flux de test doivent contenir un byte-order marker qui vous permettra de déterminer comment traiter les données binaires.

0

On ne sait pas exactement quel est votre objectif ici. D'après ce que je peux dire, il y a 2 itinéraires que vous pouvez prendre

  1. ignorera toutes les données envoyées en Unicode
  2. processus à la fois unicode et les chaînes ASCII

à mon humble avis, # 1 est la voie à suivre . Mais il semble que votre protocole ne soit pas nécessairement configuré pour gérer une chaîne Unicode. Vous devrez faire une logique de détection pour déterminer si la chaîne qui arrive est une version Unicode. Si c'est le cas, vous pouvez utiliser la méthode Enconding.Unicode.GetString pour convertir ce tableau d'octets particulier.

0

Quel type de codage vos clients utilisent-ils? Si certains de vos clients utilisent encore l'ASCII, vous aurez besoin de vos clients internationaux pour utiliser quelque chose qui mappe l'ensemble ASCII (1-127) sur lui-même, tel que UTF8. Après cela, utilisez la méthode GetString de l'encodage UTF8.

0

Ma seule solution est de réparer l'API. Indiquez aux utilisateurs d'utiliser uniquement une chaîne ASCII dans le Byte [] ou fixez-le pour prendre en charge ASCII et tout autre encodage que vous devez utiliser. Décider quel encodage est fourni par les clients étrangers à partir de l'octet [] peut être un peu compliqué.

Questions connexes