NcrCodec

@ITで数値文字参照から文字への変換に関するスレが盛り上がってるのを見ながら、暇つぶしにコーディング。

 /*
    NcrCodec
    NCR⇔文字列の相互変換。
 */

import java.util.regex.Pattern;
import java.util.regex.Matcher;

public class NcrCodec{
    // インスタンス化禁止
    private NcrCodec() {}
    
    // NCRエンコードを行う(10進表記)
    public static String encode(String str) {
        return encode(str, 10);
    }
    
    // NCRエンコードを行う(基数指定)
    public static String encode(String str, int radix) {
        String NCRheader;
        String NCRfooter = ";";
        
        if(radix == 10){
            NCRheader = "&#";
        }else if(radix == 16){
            NCRheader = "&#x";
        }else{
            // 基数は10,16しか認めない。
            throw new IllegalArgumentException("Illegal radix.");
        }
        
        StringBuffer sb = new StringBuffer();
        
        for(int i = 0 ; i < str.length() ; i++){
            sb.append(NCRheader);
            sb.append(Integer.toString((int)str.charAt(i), radix));
            sb.append(NCRfooter);
        }
        
        return sb.toString();
    }
    
    // NCRデコードを行う(10進、16進)
    public static String decode(String str) {
        Pattern pattern = Pattern.compile("&#(\\d+);|&#x([\\da-fA-F]+);");
        Matcher matcher = pattern.matcher(str);
        StringBuffer sb = new StringBuffer();
        Character buf;
        
        while(matcher.find()){
            if(matcher.group(1) != null){
                buf = new Character*1(;
            }
            matcher.appendReplacement(sb, buf.toString());
        }
        
        matcher.appendTail(sb);
        
        return sb.toString();
    }
}

コメントいいかげんすぎ<自分
decode()の"buf="で始まってる部分、もっとすっきり出来るような気がしなくもない。

*1:char)Integer.parseInt(matcher.group(1))); }else{ buf = new Character)((char)Integer.parseInt(matcher.group(2), 16

UriCodec

ついでにURI文字列のコーデック。

 /*
    UriCodec
    URI文字列⇔文字列の相互変換
 */

import java.io.UnsupportedEncodingException;

public class UriCodec{
    // インスタンス化禁止
    private UriCodec() {}
    
    /** URI文字列にエンコード。
     * @param str     エンコードする文字列
     * @param charset 使用する文字コード
     */
    public static String encode(String str, String charset) throws UnsupportedEncodingException {
        byte bytes = str.getBytes(charset);
        StringBuffer sb = new StringBuffer();
        
        for(int i = 0 ; i < bytes.length ; i++){
            sb.append("%");
            sb.append(Integer.toHexString(bytes[i] & 0xff));
        }
        
        return sb.toString();
    }
    
    /** URI文字列をデコード
     * @param str     デコードするURI文字列
     * @param charset 使用する文字コード
     */
    public static String decode(String str, String charset) throws UnsupportedEncodingException {
        byte bytes = new byte[str.length()];
        
        int j = 0;
        for(int i = 0 ; i < str.length() ; i++){
            if(str.charAt(i) == '%'){
                bytes[j++] = (byte)Integer.parseInt(str.substring(i + 1, i + 3), 16);
                i += 2;
            }else{
                bytes[j++] = (byte)str.charAt(i);
            }
        }
        
        return new String(bytes, 0, j, charset);
    }
}

encode()がいいかげんすぎ*1<自分

*1:本当は、エンコード不要な文字列はエンコードしない事が推奨されてる…はず