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