Java の URLEncoder / URLDecoder で文字化けする問題

 最近、バタバタしていてあまり記事を投稿できていませんでしたが久し振りの投稿です。

CGIでURLエンコードした文字列をJavaでURLデコードするとなぜか日本語の一部が文字化けする問題が発生していました。色々と調べていると、Perlでは2バイトコードかどうかに関係なく、1バイトずつ文字列をURLエンコードするのに対し、Javaは2バイトコードのみをURLエンコードしていることが分かりました。

ただ、どちらが間違いという事は無く、両方ともエンコーダーの実装としては正しいみたいです。ただし、Javaのデコーダーの実装が良くないみたいで、PerlでURLエンコードした文字列を正確に文字列に戻せない不具合があるようです。

しょうがないので、以下のように自前で正常に動作するURLDecoderを作成しました。


package com.tezukaosamumagazineclub.invoice.epsilon;

import java.io.UnsupportedEncodingException;

public class URLDecoder {

    public static String decode(String s, String enc) throws UnsupportedEncodingException {

        boolean needToChange = false;
        int numChars = s.length();
        StringBuffer sb = new StringBuffer(numChars > 500 ? numChars / 2 : numChars);
        int i = 0;

        if (enc.length() == 0) {
            throw new UnsupportedEncodingException("URLDecoder: empty string enc parameter");
        }

        char c;
        byte[] bytes = null;
        while (i < numChars) {
            c = s.charAt(i);
            switch (c) {
            case '+':
                sb.append(' ');
                i++;
                needToChange = true;
                break;
            case '%':

                try {

                    if (bytes == null) {
                        bytes = new byte[numChars - i];
                    }
                    int pos = 0;

                    while ((i + 2) < numChars) {
                        if (c == '%') {
                            bytes[pos++] = (byte) Integer.parseInt(s.substring(i + 1, i + 3), 16);
                            i += 3;
                        } else {

                            bytes[pos++] = (byte) Integer.parseInt(
                                Integer.toHexString(s.charAt(i)), 16);
                            i++;
                        }
                        if (i < numChars)
                            c = s.charAt(i);
                    }

                    if ((i < numChars) && (c == '%')) {
                        throw new IllegalArgumentException(
                                "URLDecoder: Incomplete trailing escape (%) pattern");
                    }

                    sb.append(new String(bytes, 0, pos, enc));
                } catch (NumberFormatException e) {
                    throw new IllegalArgumentException(
                            "URLDecoder: Illegal hex characters in escape (%) pattern - "
                                    + e.getMessage());
                }
                needToChange = true;
                break;
            default:
                sb.append(c);
                i++;
                break;
            }
        }

        return (needToChange ? sb.toString() : s);
    }
}
Be Sociable, Share!

「Java の URLEncoder / URLDecoder で文字化けする問題」への5件のフィードバック

  1. 読ませて頂きました。
    >URLDecoder で文字化けする問題
    私もこの問題に悩まされていたので、本当に助かりました。
    ありがとうございました。

  2. 自分が悩んだ問題はなるべくブログに書くようにしてますので、Javaに関係する方ならRSS登録をオススメします!(笑)

    また、遊びに来て下さい。

  3. とても参考になりました。

    “%83N” のパターンに対応していないようですね。
    sb.append(new .. の部分を

    if (i < numChars)
    bytes[pos++] = (byte)s.charAt(i++);
    sb.append(new String(bytes, 0, pos, enc));

    とすることで対応出来るようです。

  4. 本当に私 あなたのウェブサイト .. プレザント色&テーマ。 このウェブサイトあなたは なかった自分自身? 私の非常に自身の作成私はすることを望んでだとして戻って返信してくださいサイトとしたい見つけるあなたはこのを持ってどこかテーマはという名前が付けられます。 感謝!

コメントを残す

メールアドレスが公開されることはありません。