utf-8編碼解析

    javaInputStreamOutputStream讀取以字節爲單位,而ReaderWriter以字符爲讀寫單位。下面例子模仿Reader直接讀取utf-8格式編碼字符:java

public class Utf8Reader {
    private InputStream inputStream;
    //10000000取反
    private static int back10head=127;
    //11000000取反
    private static int back110head= 191;
    //11100000取反
    private static int back1110head= 223;
    //3個字節表示字符
    byte[] threeBytes = new byte[3];
    //2個字節表示字符
    byte[] twoBytes = new byte[2];
    public Utf8Reader(InputStream inputStream){
        this.inputStream=inputStream;
    }
    /**
     * 讀取一個字符
     * @return
     * @throws IOException 
     */
    public int readChar() throws IOException{
        //讀取一個字節
        int read = inputStream.read();
        //字節以1110開頭,表明用3個字節表示一個字符
        if(read>=224){
            threeBytes[0]=(byte) read;
            //讀取接下來的兩個字節
            inputStream.read(threeBytes, 1, 2);
            //將3個字節轉化爲字符
            return parseThreeByte(threeBytes);
            //字節以110開頭,即是用2個字節表示一個字符
        }else if(read>=192){
            twoBytes[0]=(byte) read;
            //讀取接下來的一個季節
            inputStream.read(twoBytes, 1, 1);
            //將兩個字節轉化爲字符
            return parseTwoByte(twoBytes);
            //字節以10開頭,只能做爲多字節字符中的一個字節,不能做爲頭部
        }else if(read>=128){
            throw new IOException("非法編碼["+read+"]字符以10開頭");
            //ASCII碼或文件結束符-1,直接返回
        }else if(read>=0){
            return  read;
        }else{
            return  -1;
        }
    }
    
    /**
     * 將2個字節轉化爲1個字符
     * 將110xxxxx 10xxxxxx 字節數值轉化爲 xxxx xxxxxx 字符
     * @param twoBytes2
     * @return
     */
    private int parseTwoByte(byte[] bytes) {
        //去掉二字節頭部表示
        int head=bytes[0]&back110head;
        //向右移6位
        head=head<<6;
        //去掉組成部分頭部表示
        int tail=bytes[1]&back10head;
        return (char) (head|tail);
    }
    /**
     * 將三個字節轉化爲1個字符
     * 將1110xxxx 10xxxxxx 10xxxxxx字節數值轉化爲 xxx xxxxxx xxxxxx字符
     * @param threeBytes2
     * @return
     */
    private int parseThreeByte(byte[] bytes) {
        //去掉三字節頭部表示
        int head=bytes[0]&back1110head;
        //向右移12位
        head=head<<12;
        //去掉組成部分頭部表示
        int second=bytes[1]&back10head;
        int third=bytes[2]&back10head;
        //第二個字符向右移6位
        second=second<<6;
        return head|second|third;
    }
}
相關文章
相關標籤/搜索