pig で URL デコード

Pocket

pig で URL デコードをしたくなる場合ありますよね。
最初に簡単な pig の Dynamic Invokers を使って URL デコードをしようと考えました

DEFINE UrlDecode InvokeForString('java.net.URLDecoder.decode', 'String String');
a = LOAD 'data.tsv' AS (enc_keyword:chararray, encode:chararray);
b = FOREACH a GENERATE enc_keyword, encode, UrlDecode(enc_keyword, encode) AS keyword;
dump b;

しかし、なぜか Shift_JIS の時だけ上手く動かない!
調べてみると に書いてあるように、
エンコード文字列の中に入っている1バイト文字のA-zの文字が問題であった

しょうがなく下記のような pig 用の UDF を作ることに・・・

package pig_UDF;

import java.io.IOException;
import java.net.URLDecoder;


import org.apache.pig.EvalFunc;
import org.apache.pig.data.Tuple;

public class UrlDecode extends EvalFunc<String> {

        /*
         * Key, Encode
         * @see org.apache.pig.EvalFunc#exec(org.apache.pig.data.Tuple)
         */
        @Override
        public String exec(Tuple input) throws IOException {
                if ( input == null || input.size() < 1)
                        return null;

                String Keyword  = input.get(0).toString();
                String Encode   = null;
                if ( input.size() == 1 || input.get(1).toString().isEmpty())
                        Encode = "UTF-8";
                else
                        Encode   = input.get(1).toString();

                // 文字化け対策
                // www.atmarkit.co.jp/fjava/rensai3/mojibake02/mojibake02.html
                if (Encode.toUpperCase().equals("SHIFT-JIS") || Encode.toUpperCase().equals("SHIFT_JIS")) {
                        Encode = "Windows-31J";


                        // SJIS の URL デコード
                        // http://www.javaroad.jp/bbs/answer.jsp?q_id=20080722151621697
                        char[] cs = Keyword.toCharArray();
                        int n = cs.length;
                        byte[] b = new byte[n];
                        int j = 0;
                        int i = 0;
                        for(i=0; i<n; i++, j++) {
                                char c = cs[i];
                                if ( c != '%') {
                                        b[j] = (byte)c;
                                } else {
                                        b[j] = (byte)(Integer.decode("0x" + cs[i+1] + cs[i+2]).intValue());
                                        i+=2;
                                }
                        }
                        return new String(b, 0, j, Encode);
                }
                else
                        return URLDecoder.decode(Keyword,Encode);
        }

}

コメントを残す