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

add to hatena hatena.comment (0) add to del.icio.us (0) add to livedoor.clip (0) add to Yahoo!Bookmark (0) Total: 0

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

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

2 件のコメント so far »

  1. rdera said,

    Wrote on 10 月 31, 2008 @ 17:04:57

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

  2. daisuke said,

    Wrote on 11 月 13, 2008 @ 11:55:30

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

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

Comment RSS · TrackBack URI

コメントする

名前:

メールアドレス:

Website:

Comment: