2009-11-16 6 views
8

ich Java bin mit dieser Anfrage zu analysierenKann nicht analysieren und Nicht-UTF-8-Zeichen aus einer HTTP-Anforderung lesen Anzeigen

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

, die diese als Folge hat (gekürzt um der Kürze halber) JSON-Datei :

{"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} 

Mein Problem liegt in den arabischen Zeichen zurückgegeben (die alle nicht Unicode für diese Angelegenheit sein könnte). Ich habe versucht, sie zurück zu Unicode wie mit etwas zu konvertieren:

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); 

jedoch sowohl das ‚vor‘ und ‚nach‘ Ergebnisse sind die gleichen: eine Reihe von ???? 's, unabhängig davon, ob I-Ausgang sie in der Serverprotokolldatei oder in einer HTML-Seite. Gibt es eine andere Möglichkeit, die arabischen Zeichen zurückzubekommen und sie auf einer Webseite auszugeben?

Does JSON hat keine für diese Art von Problem unterstützen Funktionalität vielleicht, um die Nicht-utf Zeichen sofort vom JSONObject zu lesen?

+1

Google Antwort sollte in UTF-8 sein. Sind Sie sicher, dass das von Ihnen verwendete Terminal UTF-8 unterstützt? – notnoop

+0

Welche JSON API verwenden Sie? – BalusC

+0

Die von Ihnen beschriebenen arabischen Zeichen ** sind ** in Unicode und können in UTF-8 dargestellt werden. Sie haben wahrscheinlich ein Codierungsproblem bei der Ausgabe, nicht bei der Eingabe. –

Antwort

1

Zuerst versuchen Sie dies:

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

dann die Datei in Notepad öffnen. Wenn dies in Ordnung ist, liegt das Problem in Ihrem Logger oder Ihrer Konsole, dass es nicht für die Verwendung von UTF-8 konfiguriert ist. Else das Problem am meisten liegt wahrscheinlich in der JSON-API unter der Sie, dass es nicht UTF-8 zu verwenden, ist konfiguriert.

Bearbeiten: Wenn das Problem tatsächlich in der JSON API verwendet wird und Sie nicht wissen, welche zu wählen, dann würde ich empfehlen, Gson zu verwenden. Es vereinfacht die Konvertierung einer JSON-Zeichenfolge in eine einfach zu verwendende JavaBean. Hier ist ein grundlegendes Beispiel:

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 + "]"; } 
    } 

} 

Es gibt die Ergebnisse schön aus. Hoffe das hilft.

1

Der wichtige Teil des Problems ist, wie Sie den Inhalt der HTTP-Antwort umgehen. Das heißt, wie erstellen Sie das Objekt json? Wenn Sie den Code in Ihrem ursprünglichen Post erhalten, ist der Inhalt bereits beschädigt.

Die Anforderungsergebnisse in UTF-8-Daten codiert. Wie analysierst du es in JSON-Objekte? Ist die richtige Codierung für den Decoder angegeben? Oder wird die Standardzeichencodierung Ihrer Plattform verwendet?

0

Die Google API sendet korrekt UTF-8. Ich denke, das Problem ist, dass Ihre Standard-Codierung nicht in der Lage ist, Arabisch auszugeben. Überprüfen Sie Ihre file.encoding Eigenschaft oder erhalten Codierung wie diese,

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

Wenn die Standard-Kodierung ASCII oder Latin-1, erhalten Sie „?“ S. Sie müssen es in UTF-8 ändern.

+1

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

+0

In unserem Server hat jemand diesen Anruf auskommentiert und erwähnt, dass es nicht immer funktioniert. –

+0

@BalusC: Ich habe mit mehr Kollegen über dieses Thema gesprochen. Es ist wirklich faszinierend. Ich habe eine neue Frage dazu geschrieben: http://StackOverflow.com/Questions/1749064/How-to-Find-default-charset-encoding-in-java –

7

Das Problem, das Sie haben, ist höchstwahrscheinlich durch eine falsche Einstellung der Zeichencodierung an dem Punkt verursacht, dass Sie in der HTTP-Antwort von Google lesen. Können Sie den Code posten, der URL tatsächlich erhält und in das JSON-Objekt einsortiert?

Als Beispiel führen Sie das folgende:

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()); 
    } 
} 

Dies ist das ziemlich hässlich Standard URL.openConnection() verwenden, die seit Anbeginn der Zeit gewesen ist. Wenn Sie etwas wie Apache httpclient verwenden, dann können Sie dies wirklich leicht tun.

Für ein bisschen Boden zurück auf eine Codierung zu lesen und vielleicht ein explaination, warum new String (str.getBytes(), "UTF8"); nie Joel's article on unicode

+0

+2 für mich auf die Zeichencodierungseinstellungen von 'InputStreamReader () ' –

+0

+1 es ist mir wirklich helfen .. :) –

2

Ich denke, das JSON.org Java JSON-Paket lesen arbeiten UTF8 nicht verarbeiten kann, ob er als UTF8 geben wird Zeichen oder tatsächlich die \uXXXX Code übergeben. Ich habe versucht, beide wie folgt:

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(); 
     } 
    } 
} 

ich:

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

Irgendwelche Ideen?

+0

Hallo, hast du die Lösung für dieses Problem, mein ganzes Projekt ist abhängig von json.org, so kann ich es nicht sogar lösen. –

+0

@AnkurJain Sie können Ihr Problem mit dieser Antwort http://stackoverflow.com/a/10868238/2412686 lösen und den Code org.apache.commons.lang3.StringEscapeUtils.unescapeJava ("\\ u00e9") hinzufügen (beachten Sie, dass wir Verwenden Sie eine neuere Version der Apache Commons). –

1

Es gibt eine library, die die Codierung der HTTP-Antwort (Tschechische Ausdrücke) mit JSon Meldung wie diese behält:

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(); 
} 

Die Antwort ist schwierig, und es gibt ein paar Punkte, die man darauf achten muss, vor allem zur Plattformkodierung:

afaik beeinflußt das Drucken heraus zur Konsole und verursacht Dateien von einem Eingangsstrom und sogar von der Kommunikation zwischen DB-Klient und Bediener, obwohl sie gesetzt werden, utf-8 Zeichensatz für die Kodierung zu verwenden - egal, ob ich utf ausdrücklich erstelle -8 Zeichenfolge, InputstreamReader oder JDBC-Treiber für UTF-8 setzen, noch setzen Auf Linux-Systemen die $ LANG-Eigenschaft zu xx_XX.UTF-8 hochzufahren und append = "vt.default_utf8 = 1" zum LILO-Bootloader (auf Systemen, die es verwenden) hinzuzufügen, muss mindestens für Systeme ausgeführt werden, auf denen Datenbank- und Java-Anwendungen funktionieren mit utf-8 kodierten Dateien.

Auch wenn ich diesen JVM-Parameter -Dfile.encoding = UTF-8 anfügen, ohne die Plattformcodierung gelang es mir nicht richtig codierte Streams. Der JDBC-Connector muss richtig eingerichtet sein: "jdbc: mysql: // localhost/DBname? UseUnicode = true & characterEncoding = UTF8", wenn Sie die Strings in einer Datenbank persistieren wollen, die sich in diesem Zustand befinden sollte:

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 | 
+--------------------------+--------+ 
Verwandte Themen