2011-01-16 6 views
2

J'ai un problème avec la conversion des valeurs-octets brutes dans les types de java. Je reçois des octets par un socket de datagramme en tant que tableau d'octets. Je sais exactement quels octets signifie quoi, mais je ne sais pas comment les convertir de manière appropriée (je veux dire que je connais les compensations, mais je ne sais pas si ce que je pense avoir reçu est correct;)).Conversion des valeurs octets brutes dans les types Java

Par exemple, je veux convertir court 16 bits non signé dans le type int java. J'ai trouvé quelques exemples dans le web, l'un est:

public int getUShort(byte[] bytes, int offset) { 
    int b0 = bytes[offset] & oxFF; 
    int b1 = bytes[offset + 1] & oxFF; 

    return (b1 << 8) + (b0 << 0); 

Un autre est le même, mais la dernière ligne est:

return (b0 << 8) + b1; 

Bien sûr, il donne des résultats différents. Laquelle est correcte? Pouvez-vous s'il vous plaît me donner aussi un exemple valide comment faire la même chose, mais pour un non signé longtemps?

Merci d'avance!

Répondre

1

Vous pouvez utiliser DataInputStream ou ByteBuffer pour lire les différents types. Vous pouvez utiliser des types signés en tant que valeurs non signées pour la plupart des opérations. J'ai écrit une classe simple pour illustrer comment vous pouvez utiliser les types signés comme si elles étaient non signé Unsigned

ByteBuffer b = ByteBuffer.wrap(bytes); 
short s = b.getShort(); 
long l = b.getLong(); 
+1

Vous pouvez également utiliser un [DatagramChannel] (http://download.oracle.com/javase/6/docs/api/java/nio/channels/DatagramChannel.html) qui lit directement dans un 'ByteBuffer' (pas besoin de envelopper un tableau.) – finnw

3

je devais faire un travail semblable à celui d'un certain temps et je trouve que la meilleure façon de faire ce genre de travail est d'utiliser ByteBuffer et ses conversions à DoubleBuffer, LongBuffer, etc. Vous pouvez convertir un tableau d'octets dans un ByteBuffer en appelant

ByteBuffer myBuffer = ByteBuffer.wrap(myRawArray); 

à partir de là, vous pouvez obtenir une vue des octets comme une liste de int s en appelant

IntBuffer myIntBuffer = myBuffer.asIntBuffer(); 

et vous pouvez ensuite convertir les octets en appelant

int nextInt = myIntBuffer.get(); 

Ces classes ont aussi beaucoup de soutien pour obtenir des opérations en vrac, donc si vous savez pertinemment que vous recevez un tas de données du même type sur le réseau que vous pouvez faire les conversions très rapidement.

Une autre approche serait, si possible, d'utiliser une sorte de sérialisation Java pour envoyer les données sur le réseau. Cela vous permet de faire les conversions beaucoup plus facilement en utilisant les classes d'auteur de flux. Bien sûr, cela peut ne pas être disponible, surtout si vous communiquez avec un serveur non-Java, mais cela pourrait valoir la peine d'être exploré.

+0

Le problème avec Int/Double/LongBuffer est qu'ils fonctionnent mieux si le message entier contient ces types de données. Si vous avez des types mélangés/non alignés, vous êtes mieux avec ByteBuffer. –

+0

Un bon point. Je pense que cela vaut la peine d'être mentionné, car cela pourrait être utile ici. – templatetypedef

1

vraiment en retard sur celui-ci.

sont deux réponses sont correctes en fonction de la endianess des données. Voir ici: http://en.wikipedia.org/wiki/Endianness

return (b1 << 8) + b0;//little endian 
return (b0 << 8) + b1;//big endian 
Questions connexes