2009-11-16 4 views
8

j'utilise Java pour analyser cette demandene peut pas analyser et afficher des caractères non-UTF8 lecture d'une requête http

http://ajax.googleapis.com/ajax/services/search/web?start=0&rsz=large&v=1.0&q=rz+img+news+recordid+border

qui a pour conséquence, cette (tronquée par souci de concision) fichier JSON :

{"responseData":{"results": 
<...> 
"visibleUrl":"www.coolcook.net", 
"cacheUrl":"http://www.google.com/search?q\u003dcache:p4Ke5q6zpnUJ:www.coolcook.net", 
"title":"مطبخ مطايب - كباب الدجاج والخضار بصلصة الروب", 
"titleNoFormatting":"مطبخ مطايب - كباب الدجاج والخضار بصلصة الروب","\u003drz+img+news+recordid+border"}}, 
<...> 
"responseDetails": null, "responseStatus": 200} 

Mon problème réside dans les caractères arabes sont revenus (qui pourrait être un non-unicode pour cette matière). J'ai essayé de les reconvertir en unicode en utilisant quelque chose comme:

JSONArray ja = json.getJSONObject("responseData").getJSONArray("results"); 
JSONObject j = ja.getJSONObject(i); 
str = j.getString("titleNoFormatting"); 
logger.log("before: " + str); // this is just my version of println 
enc_str = new String (str.getBytes(), "UTF8"); 
logger.log("after: " + enc_str); 

Cependant, le « avant » et « après » les résultats sont les mêmes: un ensemble de l ', que la sortie I ???? dans le fichier journal du serveur ou dans une page HTML. Existe-t-il un autre moyen de récupérer les caractères arabes et de les afficher dans une page Web?

Est-ce que JSON a des fonctionnalités de support pour ce genre de problème peut-être afin de lire les caractères non-utf directement à partir de JSONObject?

+1

La réponse de Google devrait être en UTF-8. Etes-vous sûr que le terminal que vous utilisez supporte UTF-8? – notnoop

+0

Quelle API JSON utilisez-vous? – BalusC

+0

Les caractères arabes que vous décrivez ** sont ** en Unicode et peuvent être représentés en UTF-8. Vous avez probablement un problème d'encodage en sortie, pas en entrée. –

Répondre

1

Tout d'abord, essayez ceci:

str = j.getString("titleNoFormatting"); 
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("c:/test.txt"), "UTF-8")); 
writer.write(str); 
writer.close(); 

puis ouvrez le fichier dans le bloc-notes. Si cela semble très bien, le problème réside dans votre enregistreur ou console qu'il n'est pas configuré pour utiliser UTF-8. Sinon, le problème réside probablement dans l'API JSON que vous avez utilisée et qui n'est pas configurée pour utiliser UTF-8.

Modifier: si le problème est réellement dans l'API JSON utilisée et que vous ne savez pas laquelle choisir, alors je vous recommande d'utiliser Gson. Cela facilite vraiment la conversion d'une chaîne JSON en un javabean facile à utiliser. Voici un exemple de base:

import java.io.BufferedReader; 
import java.io.InputStreamReader; 
import java.net.URL; 
import java.util.List; 

import com.google.gson.Gson; 

public class Test { 

    public static void main(String[] args) throws Exception { 
     URL url = new URL("http://ajax.googleapis.com/ajax/services/search/web" 
      + "?start=0&rsz=large&v=1.0&q=rz+img+news+recordid+border"); 
     BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream(), "UTF-8")); 
     GoogleResults results = new Gson().fromJson(reader, GoogleResults.class); 

     // Show all results. 
     System.out.println(results); 

     // Show title of 1st result (is arabic). 
     System.out.println(results.getResponseData().getResults().get(0).getTitle()); 
    } 

} 

class GoogleResults { 

    ResponseData responseData; 
    public ResponseData getResponseData() { return responseData; } 
    public void setResponseData(ResponseData responseData) { this.responseData = responseData; } 
    public String toString() { return "ResponseData[" + responseData + "]"; } 

    static class ResponseData { 
     List<Result> results; 
     public List<Result> getResults() { return results; } 
     public void setResults(List<Result> results) { this.results = results; } 
     public String toString() { return "Results[" + results + "]"; } 
    } 

    static class Result { 
     private String url; 
     private String title; 
     public String getUrl() { return url; } 
     public String getTitle() { return title; } 
     public void setUrl(String url) { this.url = url; } 
     public void setTitle(String title) { this.title = title; } 
     public String toString() { return "Result[url:" + url +",title:" + title + "]"; } 
    } 

} 

Il affiche bien les résultats. J'espère que cela t'aides.

1

La partie importante du problème est la façon dont vous gérez le contenu de la réponse HTTP. Autrement dit, comment créez-vous l'objet json? Au moment où vous obtenez le code dans votre message d'origine, le contenu a déjà été endommagé.

La requête aboutit à des données codées UTF-8. Comment l'analyse-t-on dans des objets JSON? L'encodage correct est-il spécifié pour le décodeur? Ou l'encodage de caractères par défaut de votre plateforme est-il utilisé?

0

L'API Google envoie correctement UTF-8. Je pense que le problème est que votre encodage par défaut n'est pas capable de sortir l'arabe. Vérifiez votre file.encoding propriété ou obtenir un codage comme celui-ci,

public static String getDefaultCharSet() throws IOException { 
    OutputStreamWriter writer = new OutputStreamWriter(new ByteArrayOutputStream()); 
    return writer.getEncoding(); 
} 

Si l'encodage par défaut est ASCII ou Latin-1, vous obtiendrez « ? » S. Vous devez le changer en UTF-8.

+1

'System.out.println (Charset.defaultCharset());' – BalusC

+0

Dans notre serveur, quelqu'un a commenté cet appel et a mentionné que cela ne fonctionne pas toujours. –

+0

@BalusC: J'ai parlé avec plus de collègues à propos de ce problème. C'est vraiment intrigant. J'ai posté une nouvelle question à ce sujet: http://stackoverflow.com/questions/1749064/how-to-find-default-charset-encoding-in-java –

7

Le problème que vous avez est probablement dû à un réglage incorrect du codage de caractères au point que vous lisez dans la réponse http de google. Pouvez-vous poster le code qui obtient réellement l'URL et l'analyse dans l'objet JSON?

À titre d'exemple exécutez ce qui suit:

public class Test1 { 
    public static void main(String [] args) throws Exception { 

    // just testing that the console can output the correct chars 
    System.out.println("\"title\":\"مطبخ مطايب - كباب الدجاج والخضار بصلصة الروب"); 

    URL url = new URL("http://ajax.googleapis.com/ajax/services/search/web?start=0&rsz=large&v=1.0&q=rz+img+news+recordid+border"); 
    HttpURLConnection connection = (HttpURLConnection) url.openConnection(); 
    InputStream is = connection.getInputStream(); 

    // the important bit is here..........................\/\/\/ 
    InputStreamReader reader = new InputStreamReader(is, "utf-8"); 


    StringWriter sw = new StringWriter(); 

    char [] buffer = new char[1024 * 8]; 
    int count ; 

    while((count = reader.read(buffer)) != -1){ 
     sw.write(buffer, 0, count); 
    } 

    System.out.println(sw.toString()); 
    } 
} 

Cette utilise la norme URL.openConnection() plutôt laid qui a été autour depuis l'aube des temps. Si vous utilisez quelque chose comme Apache httpclient alors vous pouvez le faire très facilement.

Pour un peu de terrain lecture arrière sur le codage et peut-être une explication des raisons pour lesquelles new String (str.getBytes(), "UTF8"); ne marchera jamais lu Joel's article on unicode

+0

+2 pour me diriger vers les paramètres d'encodage des caractères de 'InputStreamReader () ' –

+0

+1 c'est vraiment m'aider .. :) –

2

Je pense que le package JSON.org Java JSON ne peut pas gérer UTF8, si elle est adoptée en tant que UTF8 caractère ou passant effectivement dans le code \uXXXX. J'ai essayé à la fois comme suit:

import org.json. 
public class JsonTest extends TestCase { 
    public void testParseText() { 
     try { 
      JSONObject json1 = new JSONObject("{\"a\":\"\u05dd\"}"); // \u05dd is a Hebrew character 
      JSONObject json2 = new JSONObject("{\"a\":\"\\u05dd\"}"); // \u05dd is a Hebrew character 
      System.out.println(json1.toString()); 
      System.out.println(json2.toString()); 
     } catch (JSONException e) { 
      e.printStackTrace(); 
     } 
    } 
} 

je reçois:

{"a":"?"} 
{"a":"?"} 

Toutes les idées?

+0

Bonjour, avez-vous eu la solution à ce problème, mon projet entier dépend de json.org, donc je ne peux pas le résoudre même. –

+0

@AnkurJain Vous pouvez résoudre votre problème avec cette réponse http://stackoverflow.com/a/10868238/2412686, en ajoutant le code org.apache.commons.lang3.StringEscapeUtils.unescapeJava ("\\ u00e9") (notez que nous utilisez une version plus récente des communs apache). –

1

Il y a un library qui conserve le codage de la réponse http (expressions tchèques) avec le message JSon comme ceci:

private static String inputStreamToString(final InputStream inputStream) throws Exception { 
final StringBuilder outputBuilder = new StringBuilder(); 

try { 
    String string; 
    if (inputStream != null) { 
    BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8")); 
    while (null != (string = reader.readLine())) { 
    outputBuilder.append(string).append('\n'); 
    } 
    } 
} catch (Exception ex) { 
    throw new Exception("[google-api-translate-java] Error reading translation stream.", ex); 
} 

return outputBuilder.toString(); 
} 

La réponse est délicate et il y a quelques points, il faut prêter attention, principalement afaik affecte l'impression sur la console, la création de fichiers à partir d'un flux d'entrée et même la communication entre le client DB et le serveur, même si tous deux utilisent le jeu de caractères utf-8 pour l'encodage - que je crée explicitement utf -8 chaîne, inputstreamReader ou définir le pilote JDBC pour UTF-8, encore sett en ajoutant la propriété $ LANG à xx_XX.UTF-8 sur les systèmes Linux et ajouter append = "vt.default_utf8 = 1" au chargeur de démarrage LILO (sur les systèmes qui l'utilisent), au moins pour les systèmes exécutant la base de données et les applications Java avec des fichiers encodés en utf-8.

Même si j'ajoute ce paramètre JVM -Dfile.encoding = UTF-8, sans le codage de la plateforme, je n'ai pas réussi dans les flux correctement codés. La configuration du connecteur JDBC est nécessaire: "jdbc: // localhost/DBname? UseUnicode = true & characterEncoding = UTF8", si vous souhaitez conserver les chaînes dans une base de données, qui doit être dans cet état:

mysql> SHOW VARIABLES LIKE 'character\_set\_%'; 
+--------------------------+--------+ 
| Variable_name   | Value | 
+--------------------------+--------+ 
| character_set_client  | utf8 | 
| character_set_connection | utf8 | 
| character_set_database | utf8 | 
| character_set_filesystem | binary | 
| character_set_results | utf8 | 
| character_set_server  | utf8 | 
| character_set_system  | utf8 | 
+--------------------------+--------+ 
Questions connexes