pig で URL デコード

Pocket

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

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

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

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

<br />
package pig_UDF;</p>
<p>import java.io.IOException;<br />
import java.net.URLDecoder;</p>
<p>import org.apache.pig.EvalFunc;<br />
import org.apache.pig.data.Tuple;</p>
<p>public class UrlDecode extends EvalFunc&lt;String&gt; {</p>
<p>        /*<br />
         * Key, Encode<br />
         * @see org.apache.pig.EvalFunc#exec(org.apache.pig.data.Tuple)<br />
         */<br />
        @Override<br />
        public String exec(Tuple input) throws IOException {<br />
                if ( input == null || input.size() &lt; 1)<br />
                        return null;</p>
<p>                String Keyword  = input.get(0).toString();<br />
                String Encode   = null;<br />
                if ( input.size() == 1 || input.get(1).toString().isEmpty())<br />
                        Encode = &quot;UTF-8&quot;;<br />
                else<br />
                        Encode   = input.get(1).toString();</p>
<p>                // 文字化け対策<br />
                // www.atmarkit.co.jp/fjava/rensai3/mojibake02/mojibake02.html<br />
                if (Encode.toUpperCase().equals(&quot;SHIFT-JIS&quot;) || Encode.toUpperCase().equals(&quot;SHIFT_JIS&quot;)) {<br />
                        Encode = &quot;Windows-31J&quot;;</p>
<p>                        // SJIS の URL デコード<br />
                        // http://www.javaroad.jp/bbs/answer.jsp?q_id=20080722151621697<br />
                        char[] cs = Keyword.toCharArray();<br />
                        int n = cs.length;<br />
                        byte[] b = new byte[n];<br />
                        int j = 0;<br />
                        int i = 0;<br />
                        for(i=0; i&lt;n; i++, j++) {<br />
                                char c = cs[i];<br />
                                if ( c != '%') {<br />
                                        b[j] = (byte)c;<br />
                                } else {<br />
                                        b[j] = (byte)(Integer.decode(&quot;0x&quot; + cs[i+1] + cs[i+2]).intValue());<br />
                                        i+=2;<br />
                                }<br />
                        }<br />
                        return new String(b, 0, j, Encode);<br />
                }<br />
                else<br />
                        return URLDecoder.decode(Keyword,Encode);<br />
        }</p>
<p>}<br />

コメントを残す