web-dev-qa-db-ja.com

HttpURLConnectionを使用してUTF-8文字列を送信する

これまで、JSON文字列を送受信するために次のコードスニペットを使用しました。

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

上記のコードは、json文字列にUTF-8文字が含まれていても完全に機能し、すべてが正常に機能しました。

いくつかの理由により、HTTPポストリクエストの送信方法を変更し、ApacheのHttpClientではなくHttpURLConnectionを使用する必要がありました。これが私のコードです:

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

このコードは通常の英語の文字でうまく機能しますが、毎回失敗するため、json文字列でUTF-8文字をサポートしていないようです。 (サーバーにjsonを送信するとき、サーバーはutf8が特定のバイトをデコードできないと言ってつぶしますが、サーバーからutf8 jsonを受信すると、特殊文字を表示できたのでうまくいくと思います)。

サーバーはまったく変更されず、以前のコードで問題なく動作したため、この新しいコードスニペットでは問題は100%です。

Json文字列の送信を修正してUTF 8をサポートする方法はありますか?ありがとう

13
Jjang

問題はこの部分にあると思います:

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

これを行う代わりに、jsonをUTF-8としてエンコードする必要があります
UTF-8エンコーディングを表すバイトを送信します。

これを使ってみてください:

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

見る:

Charset.encode

さらに簡単な方法は、たとえばBufferedWriterのラッピング
OutputStreamWriterOutputStreamWriterは独自のエンコーディングを知っています
それであなたのために仕事をします(json文字列のエンコード作業)。

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

Stringを出力ストリーム(バイト)に書き込む場合、変換を行うためにエンコーディングを指定する必要があります。 1つの方法は、エンコードにUTF-8文字セットを使用するOutputStreamWriterで出力ストリームをラップすることです。

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

flush()を呼び出す場合、close()もオプションです。

peter.petrov で言及されている別のオプションは、最初にStringを(メモリ内の)バイトに変換してから、バイト配列を出力ストリームに出力することです。

また、サーバー側でそれを明確にするために、コンテンツタイプヘッダー(_"content-type", "application/json; charset=utf-8"_)で使用される文字セットを渡すことができます。

6
Fradenger

StringEntityCharsetを使用して、エンコーディングが正しいことを確認します。それはそれをします:

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

コードに大きな変更を加えなければ、書き込みは次のようになります。

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

読み取りについては、BufferedReaderreadLineとともに使用しても、行末を正規化する以外は意味がありません。各バイトを個別に読み取る必要があるため、他の方法よりもはるかに低速です。

EntityUtilsはほとんどそれを行います:

    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();
1
njzk2