Java

Javaで文字コードを正してURLから読み込む

経緯

  • JRubyの#openがWindows10環境だとエラーを吐く
  • Java側で実装してみよう
  • jisautodetect使うとutf-8の場合ダメだ
  • 下のコードに至る

※特定のURLだけなので普通はこんな必要ないと思います

入出力

  • 引数
    • url(変数名 : link)
    • タイムアウトする時間(変数名 : time_limit)
  • 戻り値
    • 成功時 : 正しい(?)ファイル文字列
    • 失敗時 : 空文字列

コード

JavaOpen.java
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.net.URLConnection;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;

public class JavaOpen{
    public static String open(String link, int time_limit){
        String html = "";
        try {
            URL url = new URL(link);
            URLConnection con = url.openConnection();
            con.setConnectTimeout(time_limit*300);
            con.setReadTimeout(time_limit*700);
            try (InputStream is = con.getInputStream();){
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                byte[] byteChunk = new byte[8192];
                int n;

                while ( (n = is.read(byteChunk)) > 0 ) {
                    baos.write(byteChunk, 0, n);
                }
                byte[] bytes = baos.toByteArray();
                html = bytesToHtml(bytes);
            } catch (IOException e) {
                e.printStackTrace ();
            }
        } finally {
            return html;
        }
    }

    public static String bytesToHtml(byte[] src) throws UnsupportedEncodingException {
        String[] char_codes = { "UTF8","SJIS","EUC_JP","EUC_JP_LINUX","EUC_JP_Solaris" };
        for (String cc: char_codes){
            String s_tmp = new String(src, cc);
            byte[] b_tmp = s_tmp.getBytes(cc);
            if (Arrays.equals(src, b_tmp)) {
                return s_tmp;
            }
        }
        return "";
    }
}

コメント

  • String[] char_codes = { "UTF8","SJIS","EUC_JP","EUC_JP_LINUX","EUC_JP_Solaris" }; は自分のアクセスしうる可能性がある文字コードなのでご自由にどうぞ
  • 変数名time_limitの代案が思いつきたかったです...
  • setConnectTimeout : setReadTimeout=3 : 7で配分したけど、、普通はどうなんでしょうか?
  • 8192byteずつではなく一度に読み込む方法を知りたかったけど、動けばいいやの意思に負けた

参考