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 :

Récupération d'une page web : problème d'encodage


Sujet :

Langage Java

  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    676
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2006
    Messages : 676
    Points : 121
    Points
    121
    Par défaut Récupération d'une page web : problème d'encodage
    Bonjour,

    Je cherche à récupérer le contenu d'une page web mais j'ai de vrais problèmes d'encodage.
    Lorsque j'affiche la page dans le navigateur c'est normal mais avec java ça me donne ça :

    Nom : 811408Capture.png
Affichages : 144
Taille : 5,8 Ko

    J'essaye de récupérer la page avec diverses fonctions :

    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
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
     
     
    	static String get(String adresse){
    	   BufferedReader reader = null;
    	   String retour = null;
    	   try {
    		  //création de la connection
    	      URL url = new URL(adresse.replace(" ", "%20"));
    	      URLConnection conn = url.openConnection();
    	      conn.setRequestProperty( "Host", url.getHost() );
    	      conn.setRequestProperty( "Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8" );
    	      conn.setRequestProperty( "Accept-Language", "fr,fr-fr;q=0.8,en-us;q=0.5,en;q=0.3" );
    	      conn.setRequestProperty( "Connection", "keep-alive" );
    	      conn.setRequestProperty( "User-Agent", "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)" );
    	      if(cookieValue!=null) conn.setRequestProperty("Cookie", cookieValue);
    	      if(CSRFToken!=null) conn.setRequestProperty("X-CSRFToken",CSRFToken);
    	      conn.setDoOutput(true);
     
    	      //lecture de la réponse
    	      reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
     
    			StringBuilder sb = new StringBuilder();
    			char[] cbuf = new char[8192];
    			int len;
    			while ( (len = reader.read(cbuf)) >= 0 ) {
    				sb.append(cbuf, 0, len);
    			}
    			retour = sb.toString();
    	   }catch (Exception e) {
    		   Applet_VeilleConcurentielle.erreur(e);
    		}finally{
    	      try{ if(reader!=null) reader.close(); }catch(Exception e){
    	    	  Applet_VeilleConcurentielle.erreur(e);
    	      }
    	   }
    	   return retour;
    	}
     
     
     
    	//lit une page Web
    	static String url(String adresse)
    	{
    		String code;
    		InputStreamReader reader=null;
    		try {
    	        URL u=new URL(adresse.replace(" ", "%20"));
    	        reader = new InputStreamReader( u.openStream(), "utf8" );
    			StringBuilder sb = new StringBuilder();
    			// Le buffer de lecture :
    			char[] cbuf = new char[8192];
    			// La quantité d'élément lu à chaque iteration (peut varier)
    			int len;
    			// boucle de lecture / copie 
    			while ( (len = reader.read(cbuf)) >= 0 ) {
    				sb.append(cbuf, 0, len);
    			}
    			// Copie en String :
    			code = sb.toString();
    			return code;
    		}
    		 catch (ConnectException e) {
    			 Fc.mess("Erreur de connexion :\n"+e.toString());
    			 Applet_VeilleConcurentielle.erreur(e);
    		 }
    		 catch (SocketException e) {
    			 Fc.mess("Erreur de connexion :\n"+e.toString());
    			 Applet_VeilleConcurentielle.erreur(e);
    		} catch (UnknownHostException e) {
    			 Fc.mess("Problème de connexion (hote inconnu) :\n"+e.toString());
    			 Applet_VeilleConcurentielle.erreur(e);
    		} catch (MalformedURLException e) {
    			 Applet_VeilleConcurentielle.erreur(e);
    		} catch (IOException e) {
    			 Applet_VeilleConcurentielle.erreur(e);
    		} finally {
    			// on ferme les flux
    			try {
    				if(reader!=null) reader.close();
    			} catch (IOException e) {
    				// TODO Auto-generated catch block
    				 Applet_VeilleConcurentielle.erreur(e);
    			} 
    		}
    		return null;
    	}
    Et de décoder avec ça mais rien n'y fait :

    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
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
     
    	static String utf8Encode(String txt)
    	{
    		try {
    			return new String(txt.getBytes(), "utf8");
    		} catch (UnsupportedEncodingException e) {
    			e.printStackTrace();
    		}
    		return null;
    	}
     
     
    	static String utf8Decode(String txt)
    	{
    		try {
    			return new String(txt.getBytes("ISO-8859-1"),"UTF-8"); 
    		} catch (UnsupportedEncodingException e) {
    			e.printStackTrace();
    		}
    		return null;
    	}
     
    	static String decode(String txt)
    	{
    		  CharsetDecoder d=Charset.forName("UTF-16").newDecoder();
    		  d.replaceWith("x");
    		  d.onMalformedInput(CodingErrorAction.REPLACE);
    		  d.onUnmappableCharacter(CodingErrorAction.REPLACE);
    		  ByteBuffer in=ByteBuffer.wrap(txt.getBytes());
    		  try {
    			return d.decode(in).toString();
    		} catch (CharacterCodingException e) {
    			e.printStackTrace();
    		}
    		  return null;
    	}
    Voici la requête inspectée par WebScarab : Nom : Capture.PNG
Affichages : 204
Taille : 62,2 Ko

  2. #2
    Expert éminent sénior
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Salut,




    Ton code pour décoder est complètement faux :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    return new String(txt.getBytes(), "utf8");
    Tu récupères la chaine dans l'encodage par défaut, et tu tentes de lire cela comme de l'UTF8...



    Il faut préciser l'encodage lorsque tu lis les données, pas après.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Charset chartset = ...
     reader = new BufferedReader(new InputStreamReader(conn.getInputStream(), charset));
    Au passage il est plus simple d'utiliser un try/finally à la création de la ressource, et de l'englober lui-même dans le try/catch.
    Cela évite de doubler les catch...


    a++

  3. #3
    Membre régulier
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    676
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2006
    Messages : 676
    Points : 121
    Points
    121
    Par défaut
    Merci, j'ai repris ma fonction get et j'ai mis le charset après en l'essayant avec UTF-8, UTF-16, ISO-8859-1, UTF-16LE, windows-1252, UTF-16BE mais aucun ne marche.
    Ca donne des caractères chinois ou des trucs incompréhensible.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    //lecture de la réponse
    	      reader = new BufferedReader(new InputStreamReader(conn.getInputStream(),"ISO-8859-1"));
    Si tu veux t'amuser à lire la page c'est http://www.frishop.dk/Services/Produ...www.frishop.dk

  4. #4
    Modérateur

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

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 551
    Points : 21 607
    Points
    21 607
    Par défaut
    Bleh. C'est pas un problème de charset.

    L'URL envoie une réponse avec Content-Encoding: gzip et en testant je constate que URLConnection ne le gère pas. C'est-à-dire qu'il ne s'intéresse pas à ce header, fait comme s'il n'était pas là, et ne décompresse pas à la volée la réponse envoyée.
    Il faut donc décompresser toi-même avec un GZIPInputStream.

    Apache HttpClient, lui, aurait détecté ça tout seul et l'aurait fait à ta place.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  5. #5
    Membre régulier
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    676
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2006
    Messages : 676
    Points : 121
    Points
    121
    Par défaut
    Arf, j'ai pas fini de t'embêter.

    Avec la méthode get2 que voici j'obtiens exactement le même résultat :

    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
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    	static String get2(String adresse){
    		HttpClient httpclient = new HttpClient();
     
     
    		String text = new String();
    	    GetMethod method = new GetMethod(adresse);
    	        try {
    	            // Create a method instance.
     
    	            // Provide custom retry handler is necessary
    	            method.getParams().setParameter(HttpMethodParams.RETRY_HANDLER, 
    	                    new DefaultHttpMethodRetryHandler(3, false));
    	            if(Fc.cookieValue!=null) method.setRequestHeader("Cookie",Fc.cookieValue);
     
    	            //System.out.println("executing request " + httpget.getURI());
    	            // construction de l'objet qui gerera le dialogue avec le serveur 
    	            ResponseHandler<String> responseHandler = new BasicResponseHandler();
    	            try {
    	            	httpclient.executeMethod(method);
    	                byte[] responseBody = method.getResponseBody();
    	                text = new String(responseBody); //et on y va
    	            } catch(Exception e) {}
    		}
    		catch(Throwable t) {
    		    System.out.println("Echec du chargement de "+adresse+" "+ t . toString());
    		    //t . printStackTrace();
    		}
    		finally {
    	            // Lorsque on n'a plus besoin de l'objet de type HttpClient
    	            // on ferme la connexion pour eliberer rapidement les resources
    	            // systeme qu'on avait monopolisees
    				method.releaseConnection();
    	        }
    		return text;
    	}
    Et si le passe la valeur de retour à travers cette fonction :

    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
    19
    20
    	static String dezipHTTP(String reponse)
    	{
    		ByteArrayInputStream bais = new ByteArrayInputStream(reponse.getBytes());
    		GZIPInputStream gzis;
    		StringBuilder sb = new StringBuilder();
    		try {
    			gzis = new GZIPInputStream(bais);
    			InputStreamReader reader = new InputStreamReader(gzis);
    			BufferedReader in = new BufferedReader(reader);
     
    			String readed;
    			while ((readed = in.readLine()) != null) {
    			    sb.append(readed);
    			}
    		} catch (IOException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    		return sb.toString();
    	}
    J'ai une erreur

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    java.util.zip.ZipException: invalid distance too far back
    	at java.util.zip.InflaterInputStream.read(Unknown Source)
    	at java.util.zip.GZIPInputStream.read(Unknown Source)
    	at sun.nio.cs.StreamDecoder.readBytes(Unknown Source)
    .....

  6. #6
    Modérateur

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

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 551
    Points : 21 607
    Points
    21 607
    Par défaut
    "new HttpClient()" ? "GetMethod" ? Tu utilises quelle version de HttpClient ? Moi je te parle de celle-là.

    Ce qui nous donne un code du genre :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    static String get3(String url) throws IOException {
      try(CloseableHttpClient httpClient = HttpClients.createDefault()) {
        HttpGet httpGet = new HttpGet(url);
        return httpClient.execute(httpGet, response -> EntityUtils.toString(response.getEntity()));
      } 
    }
    Avec la réponse en clair.

    Je suppose que la version que tu utilises, ne sait pas dézipper automatiquement.
    Et dans ce cas, si tu dois dézipper toi-même, tu ne dois bien sûr pas convertir le flux en String. Parce que des octets, ce n'est pas des caractères, et tu vas forcément perdre beaucoup d'information dans l'opération. Il aurait fallu utiliser InputStream ou byte[].
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  7. #7
    Membre régulier
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    676
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2006
    Messages : 676
    Points : 121
    Points
    121
    Par défaut
    Un MEGA merci !!!

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

Discussions similaires

  1. Réponses: 4
    Dernier message: 07/01/2014, 04h19
  2. problème d'impression d'une page web et css
    Par sam01 dans le forum Webdesign & Ergonomie
    Réponses: 4
    Dernier message: 25/08/2006, 23h06
  3. Réponses: 5
    Dernier message: 06/08/2006, 19h38
  4. Réponses: 3
    Dernier message: 27/04/2006, 14h23
  5. problème avec une page web sous firefox!
    Par 3psilOn dans le forum Balisage (X)HTML et validation W3C
    Réponses: 1
    Dernier message: 24/11/2004, 11h49

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