2011-06-30 3 views
5

J'essaie de lire des données à partir d'un flux binaire, dont certaines parties doivent être analysées en UTF-8.Lecture de données texte et binaires à partir de InputStream

Utilisation du InputStream directement pour les données binaires et un InputStreamReader sur le dessus de celui-ci pour le texte UTF-8 ne fonctionne pas comme le lecteur va lire avant et gâcher les données binaires suivantes, même s'il est dit de lire un maximum de n caractères.

Je reconnais que cette question est très similaire à Read from InputStream in multiple formats, mais la solution proposée ici est spécifique aux flux HTTP, ce qui ne m'aide pas. Je pensais simplement à tout lire en tant que données binaires et à convertir les pièces pertinentes en texte par la suite. Mais je n'ai que l'information de longueur des caractères en caractères, pas en octets. Ainsi, j'ai besoin que la chose qui lit les caractères du flux soit consciente de l'encodage.

Existe-t-il un moyen de dire à InputStreamReader de ne pas lire plus loin que nécessaire pour lire le nombre de caractères donné? Ou y a-t-il un lecteur qui supporte à la fois les données binaires et le texte avec un encodage et peut être basculé entre ces modes à la volée?

Répondre

2

Vous devez d'abord lire les portions binaires. Lorsque vous reconnaissez une partie des octets nécessitant un décodage UTF-8, vous devez extraire ces octets et les décoder.

DataInputStream dis = 
// read a binary type. 
int num = dis.readInt(); 
int len = dis.readUnsignedShort(); 
// read a UTF-8 portion. 
byte[] bytes = new byte[len]; 
dis.readFully(bytes); 
String text = new String(bytes, "UTF-8"); 
// read some binary 
double d = dis.readDouble(); 
+1

Le problème est qu'avec UTF8, le nombre d'octets peut être différent du nombre de caractères. Donc, je devrais trouver le nombre de caractères multi-octets dans la chaîne, lire plus d'octets et convertir à nouveau et le faire encore et encore jusqu'à ce que les chiffres correspondent. – tajmahal

+0

Je dirais que votre format n'est pas très facile à décoder et je le réparerais si vous le pouvez. Cependant, vous pouvez analyser l'UTF-8 vous-même si vous connaissez le nombre de caractères. (Mais envoyer le nombre réel d'octets serait beaucoup plus simple) –

+0

Une autre approche consiste à lire plus de données que nécessaire. Prenez le nombre de caractères attendus, par ex. substring() et convertir en UTF-8 pour déterminer la longueur. En utilisant mark() et reset() et lisez la longueur que vous connaissez maintenant. (Cela ne fonctionne que si le codage UTF-8 est exactement le même: | par exemple, l'octet nul 0 est codé de deux manières différentes.(Comme d'autres caractères peuvent l'être) –

2

Je pense que vous ne devriez pas utiliser StreamReader. Les lecteurs traitent du texte, mais vous traitez ensemble du texte et des données binaires.

Il n'y a aucun moyen. Vous devez lire les tampons binaires et interpréter votre format vous-même, c'est-à-dire trouver la position des octets d'extrait de texte et les transformer en String.

Pour simplifier cette tâche, je vous recommande de créer votre propre classe (disons ProtocolRecord). Elle devrait être sérialisable. Il contiendra tous vos champs. Vous avez maintenant 2 options:

(1) simple - utilisez le mécanisme de sérialisation java. Dans ce cas, il vous suffit d'envelopper votre flux avec DataInputStream pour la lecture et DataOutputStream pour l'écriture, puis lire/écrire vos objets. L'inconvénient de cette approche est que vous ne pouvez pas contrôler votre protocole. 2) implémentez les méthodes readObject() et writeObject() vous-même. Utilisez maintenant DataInputStream et DataOutputStream comme expliqué ci-dessus. Dans ce cas, vous devez implémenter le protocole de sérialisation, mais au moins il est encapsulé dans votre classe.

Il pense que DataInputStream est ce dont vous avez besoin.

Questions connexes