首页 > 代码库 > utf-8编码解析

utf-8编码解析

    javaInputStreamOutputStream读取以字节为单位,而ReaderWriter以字符为读写单位。下面例子模仿Reader直接读取utf-8格式编码字符:

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


utf-8编码解析