Java の URLEncoder / URLDecoder で文字化けする問題 at ミネルヴァの梟は黄昏とともに飛び始める

ミネルヴァの梟は黄昏とともに飛び始める

Follow me on Twitter: http://www.twitter.com/dddaisuke

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

with 3 comments

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

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

Written by daisuke

11月 12th, 2007 at 10:31 pm

Posted in Java

3 Responses to 'Java の URLEncoder / URLDecoder で文字化けする問題'

Subscribe to comments with RSS or TrackBack to 'Java の URLEncoder / URLDecoder で文字化けする問題'.

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

    rdera

    31 10月 08 at 17:04:57

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

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

    daisuke

    13 11月 08 at 11:55:30

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

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

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

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

    匿名

    26 8月 10 at 15:34:21

Leave a Reply