IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage Java Discussion :

Problème avec la classe String (conversion en byte)


Sujet :

Langage Java

  1. #1
    Membre confirmé
    Inscrit en
    Août 2010
    Messages
    123
    Détails du profil
    Informations forums :
    Inscription : Août 2010
    Messages : 123
    Par défaut Problème avec la classe String (conversion en byte)
    Bonjour à tous.

    Je débute en Java et je tente d'écrire un petit serveur. Les clients sont écrits en C++. Ils envoient des messages en tableau de char (= byte en Java) avec le caractère '\n' pour séparer les messages.

    Voici mon code pour récupérer les messages des clients :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    String message;
    BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
    while ((message = reader.readLine()) != null) { 
    	int pos = message.indexOf(';');
            if (pos == -1) continue;
            String cmd = message.substring(0, pos);
    	if (cmd.equals("START")) {
    		...
    	}
    	if (cmd.equals("STOP")) {
    		...
    	}
    }
    Ceci fonctionne plutôt bien. Mais seulement quand les messages des clients contiennent des caractères ASCII. Sinon la classe String de Java encode et transforme les messages reçus.

    Y a t-il moyen d'empêcher la classe String de transformer ces messages ?
    Y a t-il moyen d'avoir accès au tableau de byte reçu initialement ?
    Ou faut-il tout réécrire sans utiliser la classe String (tableau de byte) :ouïlle: ?

    Merci pour vos réponses.

  2. #2
    Rédacteur

    Homme Profil pro
    Geek entrepreneur
    Inscrit en
    Novembre 2004
    Messages
    1 224
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Geek entrepreneur

    Informations forums :
    Inscription : Novembre 2004
    Messages : 1 224
    Par défaut
    Pas sur d'avoir saisi ton souci. C'est un problème d'encodage ?

    Quand tu lis ton flux d'entrée, tu peux préciser le charset. InputStreamReader prend un charset en second paramètre.

  3. #3
    Expert confirmé
    Avatar de le y@m's
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2005
    Messages
    2 636
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Février 2005
    Messages : 2 636
    Par défaut
    Alors soit tu veux récupérer et travailler avec des bytes, dans ce cas tu travailles directement avec l'InputStream, soit tu veux travailler avec des chaînes de caractères.
    Dans ce cas là, il te faut spécifier l'encodage utilisé. En effet, si tu ne spécifies pas l'encodage, java utilisera celui par défaut du système (qui peut être différent de celui utilisé pour envoyer les données, d'où des problèmes de décodage).
    Tu dois donc t'assurer que les clients et le serveur utilise le même encodage pour se transmettre des chaînes de caractères.
    Pour spécifier l'encodage dans ton code java, tu peux utiliser le constructeur de l'InputStreamReader.
    Par exemple si tu veux utiliser l'encodage UTF8
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream(), "UTF8"));

    Plus d'infos : L'implémentation des entrées/sorties en java
    Je ne répondrai à aucune question technique par MP.

    Pensez aux Tutoriels et aux FAQs avant de poster ;) (pour le java il y a aussi JavaSearch), n'oubliez pas non plus la fonction Rechercher.
    Enfin, quand une solution a été trouvée à votre problème
    pensez au tag :resolu:

    Cours Dvp : http://ydisanto.developpez.com
    Blog : http://yann-disanto.blogspot.com/
    Page perso : http://yann-disanto.fr

  4. #4
    Membre confirmé
    Inscrit en
    Août 2010
    Messages
    123
    Détails du profil
    Informations forums :
    Inscription : Août 2010
    Messages : 123
    Par défaut
    Merci pour vos réponses.

    @hugo123 : moi même je ne suis pas sûr de tout comprendre.

    @le y@m's : il semble que j'ai réussi à faire quelque chose car effectivement les clients envoient leurs messages en UTF8. Mais il faut que je fasse encore quelques tests car je suis perdu dans les entrées / sorties. Le mal de tête guette.

  5. #5
    Membre confirmé
    Inscrit en
    Août 2010
    Messages
    123
    Détails du profil
    Informations forums :
    Inscription : Août 2010
    Messages : 123
    Par défaut
    En fait, le plus simple finalement serait d'avoir une classe proche de String ou StringBuffer (avec des fonctions bien utiles comme indexOf, substring,...) qui stockerait un tableau de bytes (et ne ferait pas d'encodage / décodage).

  6. #6
    Membre émérite
    Inscrit en
    Mars 2006
    Messages
    848
    Détails du profil
    Informations personnelles :
    Âge : 41

    Informations forums :
    Inscription : Mars 2006
    Messages : 848
    Par défaut
    Dès que tu as une notion de caractères, tu dois avoir une notion d'encodage pour utiliser des flux, sinon tu vas au devant de problèmes.

    Et comme String est une chaîne de caractères, tu ne peux pas t'en passer, à moins de traiter directement (et uniquement) avec des byte[]...

  7. #7
    Modérateur

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    12 582
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 582
    Par défaut
    Bah oui, mais c'est pas faux : supposons que dans le cas présent il ne veuille pas voir de notion de caractère, et juste transmettre les octets tels qu'il les reçoit, partitionnés par l'octet de la valeur ASCII de \n (ou par le doublet \r\n).
    START et STOP pourraient être vu comme des nombres magiques, et au pire ça pourrait être les seuls caractères de chaque partition.

    Bon, dans le cas présent je vois pas pourquoi s'embêter avec ça (et en particulier je vois mal comment ça pourrait être plus simple,) mais avec certains protocoles ça pourrait arriver.

    Quand on a besoin de faire des traitements sur des tableaux, que ce soit des byte[] ou autre chose, la classe Arrays aide bien.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  8. #8
    Membre confirmé
    Inscrit en
    Août 2010
    Messages
    123
    Détails du profil
    Informations forums :
    Inscription : Août 2010
    Messages : 123
    Par défaut
    Effectivement c'est bien le cas thelvin. En fait, je n'arrive pas à reproduire exactement le fonctionnement de l'ancien serveur C++. 90% des messages fonctionnent maintenant car je les traite en UTF8. C'est déjà très bien. Mais certains messages sont des données brutes (cmd = "DATA") que je dois stocker sans les modifier. Et là ça coince.

    J'ai deux solutions : soit modifier les clients en C++ pour qu'ils envoient les messages DATA sur un autre port, mais à la base je ne voulais pas. Soit tout ré-écrire avec des tableaux de byte, mais cela va me prendre du temps et j'ai un peu peur pour les performances n'étant pas au top avec Java.

    En tous cas, merci pour vos réponses, cela m'a fait avancer dans ma réflexion.

  9. #9
    Membre émérite
    Inscrit en
    Mars 2006
    Messages
    848
    Détails du profil
    Informations personnelles :
    Âge : 41

    Informations forums :
    Inscription : Mars 2006
    Messages : 848
    Par défaut
    Je n'avais pas tout à fait compris ton besoin, au temps pour moi.

    Dans ce cas, tu peux t'orienter vers un DataInputStream qui te permettra de lire à la fois des tableaux de byte et des String en UTF8 (et même des int, long, etc.) selon ce que tu attends.

  10. #10
    Membre confirmé
    Inscrit en
    Août 2010
    Messages
    123
    Détails du profil
    Informations forums :
    Inscription : Août 2010
    Messages : 123
    Par défaut
    Ok. Merci à tous. J'ai finalement utilisé un autre port et DataInputStream pour les messages DATA. Assez impressionné par le langage et le framework au passage.

    Une petite question subsidiaire (je n'ose pas créer une autre discussion pour ça). Il me semble que les nombreux exemples d'écriture de fichier en Java sont partiellement faux :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    try { 
         BufferedWriter out = new BufferedWriter(new FileWriter("outfilename"));
         out.write("aString"); 
         out.close(); 
         } 
    catch (IOException e) 
         { 
    }
    J'aurais tendance à faire ça pour libérer les ressources :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
     
    BufferedWriter out = null;
    try { 
         out = new BufferedWriter(new FileWriter("outfilename"));
         out.write("aString"); 
         out.close(); 
         } 
    catch (IOException e) 
         {
         try {
              if (out != null) out.close();
         }
         catch (IOException e) {
         }
    }

  11. #11
    Membre émérite
    Inscrit en
    Mars 2006
    Messages
    848
    Détails du profil
    Informations personnelles :
    Âge : 41

    Informations forums :
    Inscription : Mars 2006
    Messages : 848
    Par défaut
    En effet, la fermeture peut ne pas avoir lieu dans le premier cas.

    Ton écriture n'est pas fausse, mais pour libérer les flux, la syntaxe à utiliser est plutôt celle-ci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    try { 
         BufferedWriter out = new BufferedWriter(new FileWriter("outfilename"));
         try { 
              out.write("aString"); 
         } finally {
              out.close();
         }
    } 
    catch (IOException e) 
    { 
    }

  12. #12
    Membre Expert
    Inscrit en
    Mai 2006
    Messages
    1 364
    Détails du profil
    Informations forums :
    Inscription : Mai 2006
    Messages : 1 364
    Par défaut
    Citation Envoyé par PocoYote Voir le message
    J'aurais tendance à faire ça pour libérer les ressources :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
     
    BufferedWriter out = null;
    try { 
         out = new BufferedWriter(new FileWriter("outfilename"));
         out.write("aString"); 
         out.close(); 
         } 
    catch (IOException e) 
         {
         try {
              if (out != null) out.close();
         }
         catch (IOException e) {
         }
    }
    Au passage, tu peux faire directement :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
     
    BufferedWriter out = null;
    try { 
         out = new BufferedWriter(new FileWriter("outfilename"));
         out.write("aString"); 
         } 
    catch (IOException e) 
         {
         System.out.println("Erreur");
         }
    finally {
         try {
              if (out != null) out.close();
         }
         catch (IOException e) {
         System.out.println("Erreur");
         }
    }
    Rappelons qu'un bloc finally est toujours executé, qu'on ait une exception ou non ;-)

    a+

  13. #13
    Membre confirmé
    Inscrit en
    Août 2010
    Messages
    123
    Détails du profil
    Informations forums :
    Inscription : Août 2010
    Messages : 123
    Par défaut
    Ok. Merci Deaf.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [VB.NET]petit problème avec la classe string !!
    Par zouhib dans le forum Windows Forms
    Réponses: 6
    Dernier message: 01/06/2006, 11h58
  2. Problème avec fonctions et string/char
    Par vdumont dans le forum C++
    Réponses: 6
    Dernier message: 08/04/2006, 16h54
  3. Problème avec la classe Calendar
    Par afrikha dans le forum Collection et Stream
    Réponses: 3
    Dernier message: 30/03/2006, 08h48
  4. Réponses: 9
    Dernier message: 25/09/2005, 16h33
  5. probléme avec une date/string dans un CommandText
    Par critok dans le forum Bases de données
    Réponses: 5
    Dernier message: 09/02/2005, 15h30

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo