QA@IT

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

2977 PV

http://qa.atmarkit.co.jp/q/3362?_nid=2423
の続きです

HttpURLConnection conn = (HttpURLConnection) target.openConnection();
conn.setRequestMethod("GET");
conn.setDoOutput(true);
conn.connect();

InputStream in = conn.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
conn.disconnect();
String line = "";
while ( ( line = reader.readLine() ) != null ) {
        if ( line.contains("charset=") ) {
            nextEncoding  = line.substring( line.indexOf("charset=")+8, line.lastIndexOf("\"") );
            reader.close(); 
                conn.disconnect();
            break;
        }
}
line = "";
reader = new BufferedReader(new InputStreamReader(in, nextEncoding));
while ((line = reader.readLine()) != null) {
    tmpBody.append(line);
}
String html = tmpBody.toString();
reader.close();
in.close();
conn.disconnect();

のように一度あるURLからエンコードの部分を読み取って、そのエンコード(上記のコードのnextEncoding)に従って、再度読み取りにいくという手法で、例外が発生しています。
このような方法はいけないのでしょうか??

  • 発生している例外を示してください。 -
  • それとその例外の意味も考えてみてください。 -
  • java.io.UnsupportedEncodingException:
    at sun.nio.cs.StreamDecoder.forInputStreamReader(StreamDecoder.java:52)
    at java.io.InputStreamReader.<init>(InputStreamReader.java:83)
    という例外が出ていています
    -
  • これは一度読み込んだ際に取得した文字コードを上手く扱えていないのかと思っています -

回答

例外であるUnsupportedEncodingExceptionの意味するところは単純に
「サポートされていないエンコード」です。

つまりは第二引数のnextEncodingの文字列が、エンコードとして正しくないということです。
方法が正しいかどうかの前の話ですね。わかりにくい例外もありますが例外が報告してくれている内容に注目しましょう。

現状ではcharset属性から文字を抽出するときに+8としているから最初の二重引用符が入ってしまっているのが一因な気がしますが(多分+9が正しいんじゃないかな)、
そもそもjavaとHTMLのcharsetで指定できる文字列が同じなのか、
それ以外にも単一引用符だった場合や引用符が省略されていた場合charsetが無い場合なども想定しないといけません。

最初から全部は対応できないですが、取れなかった時にどうするか(ログ出すとかエラーにするとか)
は何かしかけておかないと、エラーが区別できなくなると思いますよ。

あと確認してないので間違ってるかもしれませんが、
reader.closeの後に再オープン出来るかどうかが気になります。


charsetの件は、html 4だとそのままで正しいですね。失礼しました。html 5の charset属性しか考えてませんでした。

編集 履歴 (2)
  • 少し書き方を変えましたが、2度アクセスすることで文字コードの問題は解決できました。ありがとうございました! -
  • 最初にバイナリでファイルに保存して、その後はそのファイルを相手にするという方法もありますね。
    -
  • charsetはhttp-equiv属性だと提示されたコードのままで正しかったですね。それについて追記しました。 -
ウォッチ

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