2014-06-05 5 views
9

bis jetzt habe ich den folgenden Code-Schnipsel, um zu senden und empfangen JSON-Strings:Senden UTF-8-String mit HttpURLConnection

static private String sendJson(String json,String url){ 
    HttpClient httpClient = new DefaultHttpClient(); 
    String responseString = ""; 
    try { 
     HttpPost request = new HttpPost(url); 
     StringEntity params =new StringEntity(json, "UTF-8"); 
     request.addHeader("content-type", "application/json"); 
     request.setEntity(params); 
     HttpResponse response = httpClient.execute(request); 
     HttpEntity entity = response.getEntity(); 
     responseString = EntityUtils.toString(entity, "UTF-8"); 

    }catch (Exception ex) { 
     ex.printStackTrace(); 
     // handle exception here 
    } finally { 
     httpClient.getConnectionManager().shutdown(); 
    } 
    return responseString; 
} 

Der obige Code perfekt gearbeitet, auch wenn die json-String enthalten UTF-8 Chars, und alles hat gut funktioniert.

Aus verschiedenen Gründen musste ich die Art ändern, wie ich HTTP-Postanfragen sende und stattdessen HttpURLConnection anstelle von Apache's HttpClient verwende. Hier ist mein Code:

static private String sendJson(String json,String url){ 
    String responseString = ""; 
    try { 
     URL m_url = new URL(url); 
     HttpURLConnection conn = (HttpURLConnection)m_url.openConnection(); 
     conn.setDoInput(true); 
     conn.setDoOutput(true); 
     conn.setUseCaches(false); 
     conn.setRequestMethod("POST"); 
     conn.setRequestProperty("content-type", "application/json"); 
     DataOutputStream outputStream = new DataOutputStream(conn.getOutputStream()); 
     outputStream.writeBytes(json); 
     outputStream.flush(); 
     outputStream.close(); 

     BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream())); 
     StringBuilder sb = new StringBuilder(); 
     String line; 
     while ((line = br.readLine()) != null) { 
      sb.append(line+"\n"); 
     } 
     br.close(); 
     responseString = sb.toString(); 
    } catch (MalformedURLException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } catch (IOException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 

    return responseString; 
} 

Dieser Code funktioniert gut für normale englische Zeichen, aber scheint nicht UTF-8-Zeichen in dem JSON-String zu unterstützen, da sie jedes Mal versagt. (Beim Senden von JSON zum Server, zerbricht der Server mit der Aussage, dass utf8 ein bestimmtes Byte nicht dekodieren kann, aber wenn ich utf8 json vom Server empfange, denke ich, dass es funktioniert, da ich die Sonderzeichen anzeigen kann).

Server hat sich überhaupt nicht geändert und funktionierte gut mit vorherigem Code, so ist das Problem 100% auf diesem neuen Codeausschnitt.

Haben Sie eine Idee, wie Sie die JSON-Zeichenkette reparieren, so dass UTF 8 unterstützt wird? Dank

Antwort

22

Ich denke, das Problem in diesem Teil ist:

DataOutputStream outputStream = new DataOutputStream(conn.getOutputStream()); 
outputStream.writeBytes(json); 
outputStream.flush(); 
outputStream.close(); 

Statt dies zu tun, Sie json als UTF-8
und senden diese Bytes codieren müssen, die die UTF-8-Kodierung darstellen.

Versuchen Sie dies mit:

Charset.forName("UTF-8").encode(json) 

See:

Charset.encode

Eine noch einfachere Methode ist die Verwendung z.B. a BufferedWriter wrapping ein
OutputStreamWriter. Die OutputStreamWriter weiß über ihre eigene Codierung
und so wird es die Arbeit für Sie tun (die Codierung der json String arbeiten).

BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(conn.getOutputStream(), "UTF-8")); 
bw.write(json); 
bw.flush(); 
bw.close(); 
+2

Perfect. Danke und haben Sie einen guten Tag. – Jjang

1

Wenn ein String mit einem Ausgangsstrom (Bytes) zu schreiben, müssen Sie die Codierung angeben, um die Konvertierung zu tun. Eine Möglichkeit besteht darin, den Ausgabestream in eine OutputStreamWriter zu verpacken, die UTF-8-Zeichensatz für die Codierung verwendet.

 conn.setRequestProperty("content-type", "application/json; charset=utf-8"); 
     Writer writer = new BufferedWriter(new OutputStreamWriter(conn.getOutputStream(), "UTF-8")); 
     writer.write(json); 
     writer.close(); 

Die flush() ist auch optional, wenn Sie close() nennen.

Eine weitere Option, wie von peter.petrov erwähnt, besteht darin, zuerst Ihre String in Bytes (im Speicher) zu konvertieren und dann das Byte-Array an Ihren Ausgabestrom auszugeben.

Und um es auf der Serverseite offensichtlich zu machen, können Sie den Zeichensatz übergeben, der im Content-Type-Header ("content-type", "application/json; charset=utf-8") verwendet wird.

1

StringEntity verwendet eine Charset, um sicherzustellen, dass die Codierung richtig ist.Es tut ~ dass:

byte[] content = s.getBytes(charset); 

Ohne große Veränderung in Ihrem Code können Sie Ihre Schreib sein:

outputStream.write(json.getBytes("UTF-8")); 

Wie für Ihre Lese, gibt es keinen Punkt in einem BufferedReader mit readLine, mit der Ausnahme zum Normalisieren das Ende der Zeile. Es ist viel langsamer als andere Methoden, da jedes Byte einzeln gelesen werden muss.

EntityUtils tut meistens, dass:

Reader reader = new InputStreamReader(conn.getInputStream(), "UTF-8"); 
    StringBuilder buffer = new StringBuilder(); 
    char[] tmp = new char[1024]; 
    int l; 
    while((l = reader.read(tmp)) != -1) { 
     buffer.append(tmp, 0, l); 
    } 
    responseString = buffer.toString(); 
Verwandte Themen