javaで外部システムと連携する際にURLデコードでハマったのでメモ。

java.net.URLDecoderはjava.net.URLEncoderと対になっていて、URLEncoder.encode(“テスト”,“Shift_JIS”)の結果である%83%65%83%58%83%67はデコード出来るけど、%83e%83X%83g(同じくShift_JISで”テスト”をURLエンコードしたもの)※1はデコードしてくれない。

そこで、%83e%83X%83gがデコードできるように自分で実装しましょう、ということ。

参照: http://blog.daisukeyamashita.com/post/227.html

上記サイトのソースをそのまま使っても良かったのですが、 微妙にバグがあるっぽかった*2ので、以下の実装としました。(キレイではないですが。。。)

package net.yosiopp.util;

import java.io.UnsupportedEncodingException;

public class URLDecoder {
  public static String decode(String src, String enc)
      throws UnsupportedEncodingException {

    String[] strings = src.split("%");
    byte[] bytes = new byte[src.length()];
    int p = 0;

    if (strings[0].length() == src.length()) {
      return src;
    }
    if(src.indexOf("%") != 0){
      for (int i = 0; i < strings[0].length(); i++) {
        bytes[p++] = (byte) strings[0].charAt(i);
      }
    }
    for (int j = 1; j < strings.length; j++) {
      String part = strings[j];
      bytes[p++] = (byte) Integer.parseInt(part.substring(0, 2), 16);
      for (int i = 2; i < part.length(); i++) {
        bytes[p++] = (byte) part.charAt(i);
      }
    }
    return new String(bytes, 0, p, enc);
  }
}

※1: %83e=0x83+‘e’=%83%65 ※2: URLエンコードされた文字列の末尾が%02x%c(16進+ASCII文字)の場合