2009-08-22 8 views
3

Je souhaite lire une chaîne d'un flux TCP donné avec une longueur d'octet suivie des données réelles. En Python, je le feraisJava NIO: lecture de blocs de taille variable

length = ord(stream.read(1)) 
data = stream.read(length) 

Comment faire la même chose dans Java NIO? Ce que j'est un tampon (capacité 257)

stream.read(buffer); // cannot specify a size here 
int length = buffer.get(); 
byte[] data = new byte[length]; 
buffer.get(data); 

Malheureusement, cela ne fonctionne pas: le get() appels lu passé les données dans la mémoire tampon :-(

j'ai probablement besoin une combinaison de flip, rewind, reset, etc., mais je ne peux pas le comprendre

+0

Quel genre d'objet est 'stream' dans votre exemple Java? – Bkkbrad

+0

C'est un SocketChannel. –

Répondre

5

si stream est un SocketChannel et buffer est un ByteBuffer, vous pouvez effectuer les opérations suivantes:

//assuming buffer is a ByteBuffer 
buffer.position(0); 
buffer.limit(1); 
while (buffer.hasRemaining()) { 
    stream.read(buffer); 
} 
buffer.rewind(); 

//get the byte and cast it into the range 0-255 
int length = buffer.get() & 0xFF; 
buffer.clear(); 
buffer.limit(length); 
while (buffer.hasRemaining()) { 
    stream.read(buffer); 
} 
buffer.rewind(); 
//the buffer is now ready for reading the data from 
+0

Merci, cela devrait bien fonctionner - même si cela semble assez compliqué. –

+1

Verbose, pas compliqué. –

+0

ce n'est pas si simple, il faut garder à l'esprit qu'il n'est pas nécessaire de recevoir tous les octets en même temps ou peut avoir reçu plusieurs messages à la fois. –

0

Je suggère, vous jetez un coup d'oeil dans java.nio.channel.GatheringByteChannel et DatagramChannel.Vous devrez spécifier un Datagramme pour vos besoins

vous avez fait par votre exemple Python (premier octet indique la longueur de la charge utile, lire la charge de lecture en utilisant cette longueur), ce qui semble vraiment fautif (!).

Un datagramme est une spécification pour un flux de données. Il divise votre flux en paquets, logiquement. Donc, une meilleure stratégie serait d'envoyer un paquet de charge utile en premier, qui indique la longueur de la charge utile (et la taille du paquet). Edit: Bien sûr, les deux côtés du flux doivent parler le même langage de protocole/datagramme.

+0

Je ne comprends pas votre recommandation. GatheringByteChannel est une interface déjà implémentée par SocketChannel que j'utilise déjà - AFAIU, c'est le canal standard à utiliser pour TCP. DatagramChannel n'est pas pertinent, car c'est pour UDP, et je fais TCP. Je ne vois pas non plus pourquoi avoir un protocole qui envoie d'abord la longueur et ensuite la charge utile est sujette aux erreurs - c'est ainsi que fonctionne le protocole HTTP 1.1, par exemple. –

+0

J'ai raté quelques détails avec votre problème. Vous penserez, vous avez plus de problème avec l'allocation qu'avec les méthodes de ByteBuffer;) Quoi qu'il en soit, Si votre charge ne dépasse pas 255 octets, la solution de Bkkbrad est simple. – cafebabe

Questions connexes