QA@IT

HTTPリクエストの文字コード

5175 PV

HTTPのリクエストで文字コードを認識する方法を教えてください。
JavaのクライアントアプリケーションでHTTPのリクエストを行なう場合、
大体以下のようなコードを書くと思います。

URL url=new URL("http://**********"); 
HttpURLConnection con=(HttpURLConnection) url.openConnection(); 
con.setRequestMethod("GET"); 
con.connect(); 
BufferedReader br=new BufferedReader(new InputStreamReader(con.getInputStream())); 
String field; 
while((field=br.readLine())!=null) 
System.out.println(field); 
con.disconnect(); 

しかしこのやり方では、InputStreamReader()で文字エンコーディングを指定していないために、サイトによっては文字化けを起してしまいます。

  • getContentType()メソッドを使って charsetを取得する方法を加えてみたのですが、Content-Typeヘッダにcharsetが指定されていないもの多くて改善にはなりませんでした。
  • 次に、HTML文書内のMETA宣言のhttp-equiv属性で設定された Content-Typeヘッダのcharsetパラメータを参照する方法を取ろうと思ったのですが、ここで矛盾にぶつかりました。

取得したcharsetは、InputStreamReader()を呼び出す際のパラメータとして使用したいのに、charsetを取得する為に そのInputStreamReader()を呼び出さなくてはならないからです。
どのように書けばうまく行くのか? ご存知の方がいらっしゃいましたら教えてください。

  • こちらの質問もどうするのか、自己回答して解決にするなどきちんと処理してください。 -

回答

JavaのクライアントアプリケーションでHTTPのリクエストを行なう場合、大体以下のようなコードを書くと思います。

サンプルコードとしてはそういったコードになりますが、実際にはそのようなコードにはなりません(それでは足りません)。
ステータスコードの判断や例外処理も入ってくるでしょう。InputStreamReaderにも文字コードを指定するべきでしょうね(自サーバーで文字コードがルール決めされていてわかっているページならば文字コードは限定できるだろうが、一般に文字コードを指定せずにどこのHTMLでも読めると思うのが間違い)。

文字化けしている原因もInputStreamReaderで文字コードを固定(というか指定せず)開いているから起きています。矛盾ではありません。

文字コードがわからないのにどうすればよいかですが、まずはバイナリで読み込めば良いと思います。その後それを元に情報を解析して適切な文字コードでそのバイナリを評価することになるでしょう。

基本的に文字コードを判断してくれるのはブラウザです。
ただ、過去の質問

http://qa.atmarkit.co.jp/q/3343
http://qa.atmarkit.co.jp/q/3351

を見るに、ブラウザに似た挙動のものを作ろうとされているように見受けられます。
つまりURLで指定されたリソース(HTML)を取得し、HTMLも解析してそのHTMLが要求するリソースも取得するような処理です。
こういったものを作成したいのであれば、HTTP通信というかブラウザがユーザーに内容を表示するまでを一旦何かで学ばれた方がいいと思います。

または別のHTMLを解析してくれるもの(サーブレットで使えるかわかりませんが、javafxのwebviewとか)に解析を任せてそこからHTMLだけ取得するという手もあります。その場合も適切に文字コードを取得できるとは限りません。

ちなみに、charsetは必須ではありませんしブラウザが内容から自動で文字コードを判別している場合もあります。それでも文字化けが起こることもあります(そもそもファイルが壊れていることすら考えられます)。
妥協点をどこにするかも大事なところだと思います(一旦妥協しても、後日精度をあげるとか)。

以前も書きましたが、他所のサーバーなどに対して何か処理する場合は迷惑にならないよう気を付けて実施してください。

編集 履歴 (0)
  • field_onion様。http://qa.atmarkit.co.jp/q/3363 こちらに新たに質問させていただきましたので、見ていただけると嬉しいです。 -
ウォッチ

この質問への回答やコメントをメールでお知らせします。